一、策略模式的定义与特点
1、定义:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的用户。
2、优点:
- 类的行为被封装进一组类中,可以被轻易地扩充与改变,如果需要,甚至可以在运行时改变行为
- 多重条件语句不易维护,使用策略模式可以避免使用多重条件语句。
- 提供相同行为的不同实现,可以根据不同条件选择不同的行为。
- 扩展性好,方便增加新的行为实现,不用修改原代码,只要增加即可。
3、缺点:
- 策略类数量可能会很多,每个策略都是一个类,复用的可能性小
- 所有的策略类都要对外暴露
二、策略模式满足的OO设计原则:
1、找出应用中可能需要变化之处,把它们独立出来进行封装,不要和那些不需要变化的代码混在一起,这样做的好处是:一旦它真的变化了,只要更改相应部分即可,其他部分不会受到影响,这样代码变化引起的不经意后果变少,系统变得更有弹性。
2、针对接口编程,而不是针对实现编程,即尽量将需要实现的功能/系统先进行抽象总结,形成接口,而具体的行为或者说实现部分作为可能会变化的部分,独立出来单独编码,一旦变化则其引起的后果会降低。
3、多用组合,少用继承。
三、策略模式的结构
1、抽象策略类:定义了公共接口
2、具体策略类:封装了具体的实现算法或行为,继承自抽象策略类
3、上下文/环境:用来维护一个对抽象策略类的对象的引用
四、策略模式的应用
1、何时使用:一个系统有许多类,而区分它们的只是它们的行为时
2、使用场景:算法或者说策略需要自由切换的场景;
3、注意事项:如果一个系统的策略多于四个,需要考虑使用混合模式来解决策略类膨胀的问题
五、具体实现(完整代码保存在github上)
1、抽象策略类:定义公共接口
public abstract class Duck{ FlyBehavior flyBehavior; QuackBehavior quackBehavior; public Duck(){ } public abstract void display(); public void performFly(){ flyBehavior.fly(); } public void performQuack(){ quackBehavior.quack(); } public void swin(){ System.out.println("All ducks float,even decoys!"); } }
2、具体策略类:封装具体的实现行为
(1)封装鸭子叫的行为
public class Quack implements QuackBehavior{ public void quack(){ System.out.println("Quack"); } }
(2)封装鸭子的飞行方式
public class FlyWithWings implements FlyBehavior{ public void fly(){ System.out.println("I'm flying!"); } }
3、上下文/环境:维护对抽象策略类的引用
public class MallardDuck extends Duck{ public MallardDuck(){ quackBehavior = new Quack(); flyBehavior = new FlyWithWings(); } public void display(){ System.out.println("I'm a real Mallard duck"); } }
4、调用上述代码
public class MiniDuckSimulator{ public static void main(String[] args){ Duck mallard = new MallardDuck(); mallard.performQuack(); mallard.performFly(); } }
最终的输出结果是:
参考资料
[1] Head First 设计模式