2016-03-21 7 views
2

Ich versuche, ein State-Machine-Entwurfsmuster in PHP zu implementieren. Das Programm führt einen Methodenaufruf für ein Wrapper-Objekt aus, das Zustandsübergänge kennt. Das Statusobjekt führt die Aktion aus, aber jedes Statusobjekt verfügt über eine andere Schnittstelle, die den verfügbaren Methoden des Status entspricht. Dies geschieht, um eine Funktion zu kapseln, so dass das Objekt keine Methodendefinition für jede mögliche Aktion haben muss, die an dem Objekt während seiner Lebenszeit ausgeführt werden kann, da dies ein nicht handhabbares Objekt wäre.PHP: Wie kann man ein Interface zur Laufzeit fälschen?

//Psuedo-code: 
class StatefulObject{ 
    protected $state; 
    /* the dynamically set state order prevents us from having 
    * to give states knowledge of eachother. 
    */ 
    protected $dynamicallySetStateOrder; 
    public function __call($name, $arguments){ 
     /* 
     * we pass all method calls to the state object 
     * the state object performs the action on the 
     * StatefulObject 
     */ 
     if(method_exists($this->state, $name)){ 
      $this->state->$name($arguments); 
     } 
    } 
} 
interface StateInterface{ 
    public function setStatefulObject($obj); 
    /* 
    * a state does not know about states before and after, but it 
    * knows if an object meets the prerequisites to enter its own 
    * state 
    */ 
    public function willAcceptStatefulObject($obj); 
} 
class State1 implements StateInterface{ 
    public function action1(...){ ... } 
    public function action2(...){ ... } 
    public function action3(...){ ... } 
    ... 
    public function action99(...){ ... } 
} 
class State2 implements StateInterface{ 
    public function actionA(...){ ... } 
    public function actionB(...){ ... } 
    ... 
    public function actionZ(...){ ... } 
} 

Das Problem kommt dann, wenn ich versuche, ein StatefulObject in eine Methode zu übergeben, Type Hinting verwendet ein Objekt zu beschreiben, die in einem particlar Zustand befindet. Wenn ich zum Beispiel eine Methode someMethod(State2 $obj) haben möchte, möchte ich die StatefulObject übergeben können, ohne der StatefulObject eine Definition für jede Methode geben zu müssen, die in allen Objektzuständen gehandhabt wird, die sie halten kann.

Die StatefulObject implementiert die Schnittstelle des Objekts in ihm enthalten ist, aber PHP wäre dies nicht sehen und eine Ausnahme auslösen würde, wenn die StatefulObject derzeit ein State2 Objekthalte waren in someMethod weitergegeben werden. Wie kann ich den Systemkomponenten dynamisch eine Schnittstellenillusion geben?

+0

Sie sollten in der Lage sein, die Schnittstelle einzugeben. Wenn das aus irgendeinem Grund nicht funktioniert, können Sie immer Ihre eigene Typ-Check-Logik am Anfang von '__call()' implementieren. –

+0

Könnten Sie das näher erläutern? –

Antwort

0

Die Antwort scheint in der Änderung des Entwurfsmusters zu sein. Anstatt den Status im StatefulObject zu speichern, verpacke ich das StatefulObject jetzt in den Status und verwende den Typhinweis basierend auf dem Status und nicht auf StatefulObject.

Mein aktuelles System hat jetzt einen hybriden Ansatz zum State Design Pattern, wenn die Schnittstelle gleich bleibt, aber das Verhalten sich ändert, ich übergebe das StatefulObject und es ruft die Methode des Staates auf, um die Aktion auszuführen. Wenn die Schnittstelle anders sein muss, überlasse ich stattdessen den Zustand. Der Status bezieht sich auf das Objekt und das Objekt bezieht sich auf den Zustand.

enter image description here

Methoden, die Verfahren von State1 bereitgestellt erfordern erhalten ein State1 Objekt, das das Objekt im Inneren mit sich führt. Methoden, die eine allgemeinere Schnittstelle erfordern, werden StatefulObject übergeben, und das StatefulObject trägt den Status. Wenn es durch das System läuft, ist es fast wie ein Möbius: Sein Inneres wird immer wieder außen, um den Zweck des Augenblicks zu erfüllen.

Verwandte Themen