2017-10-13 2 views
0

Ich benutze das Designmuster Decorator in PHP, und ich habe ein Strukturproblem.Decorator Muster mit Methodenrelation

Hier ist ein einfaches Beispiel, mein Problem zu veranschaulichen:

interface MyInterface { 
    function showUsers($array); 
    function showUser($i); 
} 

class MyCLass implements MyInterface { 

    function showUsers($array) 
    { 
     foreach($array as $toto) { 
      $this->showUser($toto); 
     } 
    } 

    function showUser($i) 
    { 
     echo $i; 
    } 
} 

class MyCLassDecorator implements MyInterface { 

    private $inner; 

    public function __construct(MyInterface $inner) 
    { 
     $this->inner = $inner; 
    } 

    function showUsers($array) 
    { 
     $this->inner->showUsers($array); 
    } 

    function showUser($i) 
    { 
     echo "User: $i"; 
    } 
} 

class MyCLassDecorator2 implements MyInterface { 

    private $inner; 

    public function __construct(MyInterface $inner) 
    { 
     $this->inner = $inner; 
    } 

    function showUsers($array) 
    { 
     $this->inner->showUsers($array); 
    } 

    function showUser($i) 
    { 
     $this->inner->showUser($i); 
     echo " is wonderful"; 
    } 
} 

$myClass = new MyCLassDecorator2(new MyCLassDecorator(new MyCLass())); 

$myClass->showUsers(["Alfred", "Bob", "Claire"]); 

Mit diesem Code der Methoden von MyClassDecorator & showuser MyClassDecorator2 wird nie aufgerufen werden.

Was kann ich tun? Ist es verboten, eine andere Methode derselben Klasse aufzurufen? (Nicht wirklich praktisch, meinen Code zu teilen) Gibt es eine andere Möglichkeit, dies zu tun? Sollte ich eine Schnittstelle nach Methode erstellen?

Vielen Dank :)

EDIT:

Hier ist die Lösung, die ich schließlich verwendet, obwohl ich es nicht wirklich zufrieden bin ...

ich meinen Code aufgespalten nicht in Methoden, aber in Schnittstellen (Dienste)

Hier ist sie:

interface IShowUsers { 
    function showUsers($array); 
} 
interface IShowUser { 
    function showUser($user); 
} 

class Services { 
    static $showUsers; 
    static $showUser; 
} 

class MyShowUsers implements IShowUsers { 

    function showUsers($array) 
    { 
     foreach($array as $toto) { 
      Services::$showUser->showUser($toto); 
     } 
    } 
} 

class MyShowUser implements IShowUser { 
    function showUser($user) 
    { 
     echo $user; 
    } 
} 

class MyShowUserDecorator implements IShowUser { 

    private $inner; 

    public function __construct(IShowUser $inner) 
    { 
     $this->inner = $inner; 
    } 

    function showUser($user) 
    { 
     echo "User: "; 
     $this->inner->showUser($user) 
    } 
} 

class MyShowUserDecorator2 implements IShowUser { 

    private $inner; 

    public function __construct(MyInterface $inner) 
    { 
     $this->inner = $inner; 
    } 

    function showUser($user) 
    { 
     $this->inner->showUser($user); 
     echo " is wonderful"; 
    } 
} 

$myClass = new MyShowUserDecorator2(new MyShowUserDecorator(new MyShowUser())); 

Services::$showUsers = new MyShosUsers(); 
Services::$showUser = new MyShowUserDecorator2(new MyShowUserDecorator(new MyShowUser())); 

Services::$showUsers->showUsers(["Alfred", "Bob", "Claire"]); 

Wenn Sie eine bessere Lösung haben, werde ich glücklich sein es

Natürlich, ich benutze die Decorator-Muster wie diese Dekorateure in unterschiedlicher Weise in vielen Projekten zu nutzen zu wissen :) in diesem exemples:

//no decorators 
Services::$showUser = new MyShowUser(); 

//only the first 
Services::$showUser = new MyShowUserDecorator(new MyShowUser()); 

//only the second 
Services::$showUser = new MyShowUserDecorator2(new MyShowUser()); 

So scheint die Erweiterung keine gute Lösung zu sein.

Vielen Dank noch einmal für die richtige Art und Weise zu geben, dies zu tun :)

Antwort

0

Es scheint mir, Sie dies ein wenig zu überdenken müssen. Wenn Sie sich ein klares Bild davon machen können, was Sie erreichen möchten, können wir Ihnen mehr Einblick geben. Aber um Ihre Frage direkt zu beantworten, können Sie extend die Klasse und dann override die Methode.

http://sandbox.onlinephpfunctions.com/code/61c33b0ce98631986134bf78efcd0391f9b9ab67

<?php 
interface MyInterface { 
    function showUsers($array); 
    function showUser($i); 
} 

class MyCLass implements MyInterface { 

    function showUsers($array = ["Alfred", "Bob", "Claire"]) 
    { 
     foreach($array as $toto) { 
      $this->showUser($toto); 
     } 
    } 

    function showUser($i) 
    { 
     echo $i; 
    } 
} 

// Extend the class in order to override the methods. 
class MyCLassDecorator extends MyCLass { 

    // Also, try removing this method to see what it does. 
    function showUsers($array = [1,2,3]) 
    { 
     foreach($array as $toto) { 
      $this->showUser($toto); 
     } 
    } 

    function showUser($i) 
    { 
     echo "c'est la fete chez $i"; 
    } 
} 

$myClass = new MyCLassDecorator(); 

$myClass->showUsers(); 

EDIT

nicht sicher, ob ich klar oder nicht ich sein, aber das Problem sind ist man Vererbungsverhalten erwarten ohne Erbe zu verwenden. Wie soll MyCLass über MyCLassDecorator::showUser wissen?

foreach($array as $toto) { 
    // The issue is this line. You're mixing `decorator` and `inheritance`. 
    // You should re-think your design. This will not work. 
    $this->showUser($toto); 
} 
+0

Ja, in diesem kleinen Beispiel wäre es ein guter Weg, um es zu beheben, aber ich habe dieses Problem in Symfony Services mit viel komplexere Funktionen und mehr Dekoration Kapselung. Also muss ich das Decorator-Muster beibehalten, um zu vermeiden, dass die Overridings gelöscht werden. –

+0

Sie verwenden das Dekorationsmuster nicht korrekt und Sie haben Ihren Code bearbeitet, sodass mein Beispiel jetzt veraltet ist. Sie rufen '$ this-> inner-> showUsers ($ array);' das 'showUsers' für eine Instanz von' MyCLass' aufruft, deshalb verwendet es 'MyCLassDecorator :: showUser' nicht.Sie müssen entweder die Klasse "erweitern", damit sie über Methoden informiert, die überschrieben werden, oder Sie müssen das Dekoratormuster korrekt verwenden. Ich werde sehen, ob ich ein Beispiel finden kann. – waterloomatt

+0

Ich habe meinen Beitrag bearbeitet, du wirst jetzt vielleicht besser verstehen, was ich brauche :) Und ich präzis, dass ich vorher nicht weiß, in welcher Reihenfolge die Dekorateure verwendet werden. –