PHP设计模式---策略模式(Strategy Pattern)

封装变化 多用组合少用继承 针对接口编程,不要针对实现编程

定义

定义了算法族,分别封装起来,让它们之间可以互相替换, 此模式让算法的变化独立于使用算法的客户。
把有变化的行为抽离出去,进行封装,分别作为接口,用多台去不同的实现这些接口,这就组成了一族算法,在本类中定义变量去引用这个接口的子类对象
用相对应的行为方法中用这个引用的子类对象去实现这个算法;这样这个类就不在关心到底进行什么样的算法,只关心引用什么样的接口对象,解耦,灵活

优点

实现客户端代码与具体的算法类解耦,具体的动作都被封装到具体算法类中 ,只要调用上下文类来选择引用具体的那种算法类,
当我要添加一种新的算法的时候只要实现算法接口,实现自己想要的算法就OK了,不需要修改原来的代码,这就体现了对扩展开放对修改关闭的原则,需要注意的是,这里客户要传给上下文这个引用算法类一个明确的指示,要这个类来决定引用那种算法,这种一般就是用参数的方法,有客户端代码决定

缺点

当每个算法步骤比较多的时候,那么实现这个这些步骤的子类写的代码就会多 ,可能有好多步骤是相同的 ,代码先得不够精炼;但是还必须出现在每个子类中 ,这就违背了
我们就可以把接口做成抽象类 ,让这些重复累赘的操作在父类中实现,不出现在子类中即可

代码实例

1. 首先来看策略,也就是定义算法的接口,示例代码如下:
public interface Strategy {
    //某个算法的接口,可以有传入参数,也可以有返回值
    public function  algorithmInterface();
}
2. 该来看看具体的算法实现了,定义了三个,分别是ConcreteStrategyA、ConcreteStrategyB、ConcreteStrategyC
public class ConcreteStrategyA implements Strategy {

    public function  algorithmInterface() {
    //具体的算法实现   
    }
}    

public class ConcreteStrategyB implements Strategy {

    public function  algorithmInterface() {
    //具体的算法实现   
    }
}    

public class ConcreteStrategyC implements Strategy {

    public function  algorithmInterface() {
    //具体的算法实现   
    }
}
3. 上下文对象,通常会持有一个具体的策略对象
public class Context {

    // 持有一个具体的策略对象
    private $strategy;

        //构造方法,传入一个具体的策略对象(@param aStrategy 具体的策略对象)
    public Context(Strategy $aStrategy) {// 类型约束,实现接口的类,这里是有客户决定到底传那种算法子类到这个上下文类中
       this->strategy =$aStrategy;
    }

    //上下文对客户端提供的操作接口,可以有参数和返回值
    public function contextInterface() {
       //通常会转调具体的策略对象进行算法运算
       $this->strategy->algorithmInterface();
    }

}

备注

其实就是把需要变化的东西抽离出去,做成接口,用多态的方式去实现这些接口,通过引用不同的多态子类对象,调用子类的不同方法。这样我可以对接口进行不同的实现。通过这个我自定义的实现来实现扩展,当然也就不会影响其他的代码了。