PHP:如何在运行时伪造接口?

时间:2016-03-21 19:38:53

标签: php interface type-hinting

我正在尝试在PHP中实现状态机设计模式。该程序在知道状态转换的包装器对象上进行方法调用。状态对象执行操作,但每个状态对象具有与状态的可用方法匹配的不同接口。这样做是为了封装函数,以便对象不需要为对象在其生命周期内执行的每个可能操作都有一个方法定义,因为这将是一个无法管理的对象。

//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( ... ){ ... }
}

当我尝试将StatefulObject传递给使用Type Hinting描述处于特定状态的对象的方法时,问题就会到来。例如,如果我希望有一个方法someMethod( State2 $obj ),我希望能够传递StatefulObject,而不必为所有对象中处理的每个方法赋予StatefulObject定义声明它可以持有。

StatefulObject实现其中包含的对象的接口,但是PHP不会看到这个并且如果要传递当前持有StatefulObject对象的State2则会抛出异常进入someMethod。如何动态地为系统组件提供界面错觉?

1 个答案:

答案 0 :(得分:0)

答案似乎在于改变设计模式。我现在将StatefulObject包装在状态中,并使用基于状态而不是StatefulObject的类型提示,而不是将状态存储在StatefulObject中。

我现在的系统现在采用状态设计模式的混合方法,当接口保持不变但行为发生变化时,我传递StatefulObject并调用状态的方法来执行操作。当界面需要不同时,我会通过状态。状态引用对象,对象引用状态。

enter image description here

需要State1提供的方法的方法接收一个State1对象,该对象随身携带对象。需要更通用接口的方法传递StatefulObject,StatefulObject携带状态。当它通过系统时,它几乎就像一个Mobius:它的内部一次又一次地变成它的外部以满足当下的目的。