声明: 本文
内容属于《Head First 设计模式》阅读笔记
,文中涉及到的知识案例等直接或间接来源于该书。《Head First 设计模式》
通过有趣的图表+文字的形式,让人自然学习设计模式,非常棒
,推荐阅读
。
策略模式概念:
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
案例(辅助理解):
提示: 策略模式使用灵活,下面只是一个简单的例子,在不同的情境下,可能有不同的表现形式。
情景介绍:
现在有一个鸭子游戏,所有的鸭子都能游泳swim,都有自己的外观display。部分鸭子能飞,而且飞的方式可能各不一样,部分鸭子能叫,可能叫的方式也各不一样。
普通方式:
因为所有的鸭子都能游泳swim,都有自己的外观display,所以使用继承的方式,创建父类鸭,父类鸭有swim以及display方法,各个不同的子类鸭均继承父类鸭,这下各个子类鸭就有了swim和display的能力了(如果有需要,还可以进行方法重写);然后对于飞行和叫,可以抽象为接口,各个子类鸭根据自己的不同的情况,实现飞行接口、叫接口即可。
使用策略模式的方式:
对于飞和叫这样的行为,单独抽取为行为两个接口,并对这两个接口分别进行算法族实现(即:一系列实现)。创建父类鸭,父类鸭本身不仅有swim和display的能力,还持有两个接口。各子类鸭只需要对这两个接口属性提供不同的策略实现即可。当子类有对飞或对叫的功能变化的需求时,可以通过setter方法进行切换。UML图如下所示:
在父类鸭中可以将飞行为或叫行为委托给策略算法族了:
这样一来,在子类鸭继承父类鸭时,主动指定具体的飞行为或叫行为即可,如:
就算在程序中,想要切换子类鸭的飞行为或叫行为,只需要使用setter方法指定即可,如:
如果直接用子类实现飞行为或叫行为的接口的话,那么具体的行为就和具体的鸭死死绑定在了一起,程序扩展性维护性差,此时使用策略模式优势一览无疑。
上述策略模式示例中的几个核心类:
- Duck
import com.szlaozicl.designpattern.strategy.fly.FlyBehavior; import com.szlaozicl.designpattern.strategy.quack.QuackBehavior; import lombok.Getter; import lombok.Setter; /** * 父类鸭 * * 注: 如果是在各个子类中直接实现FlyBehavior或QuackBehavior的话,那么子类的 * 飞或叫行为就是定死了的。而如果将其作为一个属性的话,那么子类中可以通 * 过setter等方式来指定其具体实现,从而达到切换子类能力的功能。 * * @author JustryDeng * @date 2019/10/1 19:47 */ public class Duck { /** 飞 属性 */ @Setter @Getter protected FlyBehavior flyBehavior; /** 叫 属性 */ @Setter @Getter protected QuackBehavior quackBehavior; /** * 所有鸭子都能游泳 */ public void swim() { System.out.println("鸭子游泳咯!"); } /** * 所有鸭子都有外观 */ public void display() { System.out.println("鸭子外观 ma gia gia 的!"); } /** * 调用flyBehavior的fly方法 * * 即:这里将 飞 委托给了flyBehavior的具体实现 */ public void performFly() { flyBehavior.fly(); } /** * 调用quackBehavior的quack方法 * * 即:这里将 叫 委托给了quackBehavior的具体实现 */ public void performQuack() { quackBehavior.quack(); } }
- DecoyDuck
/** * 诱饵鸭 * * @author JustryDeng * @date 2019/10/1 20:05 */ @SuppressWarnings("unused") public class DecoyDuck extends Duck { /** * 构造方法 * * 注:在构造方法中指定初始化的 飞 和 叫 的行为实现 */ public DecoyDuck() { // 诱饵鸭 能火箭助力飞, 能呱呱叫 this.flyBehavior = new FlyRocketPowered(); this.quackBehavior = new Quack(); } /// other.... }
- FlyBehavior
/** * 飞 * * @author JustryDeng * @date 2019/10/1 19:50 */ public interface FlyBehavior { /** * 飞 */ void fly(); }
- FlyRocketPowered
/** * 火箭助力飞 实现 * * @author JustryDeng * @date 2019/10/1 20:11 */ public class FlyRocketPowered implements FlyBehavior { @Override public void fly() { System.out.println("火箭助力飞~"); } }
- FlyWithWings
/** * 用翅膀飞 * * @author JustryDeng * @date 2019/10/1 19:52 */ public class FlyWithWings implements FlyBehavior { @Override public void fly() { System.out.println("用翅膀飞~"); } }
- QuackBehavior
/** * 叫 * * @author JustryDeng * @date 2019/10/1 19:51 */ public interface QuackBehavior { /** * 叫 */ void quack(); }
^_^ 如有不当之处,欢迎指正
^_^ 参考资料
《Head First 设计模式》Eric Freeman & Elisabeth Freeman with Kathy Sierra & Bert Bates著,O’Reilly Taiwan公司译,UMLChina改编
^_^ 测试代码托管链接
https://github.com/JustryDeng…DesignPattern
^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng