24,策略模式(Strategy)
24.1,问题引入_鸭子问题
- 有各种鸭子(如:北京鸭,野鸭,玩具鸭),鸭子存在各种行为(如:叫,游泳,飞行等)。需要做一个程序,显示鸭子的各种信息
- 在传统方案中,通过定义一个抽象的
Duck
类,用具体鸭子类继承该类,进行相对应的行为实现 - 首先:通过继承,会让所有具体鸭子类有共同是行为方式,这是明显不合适的
- 其次:通过方法重写,为不同的鸭子实现不同的实现方式,这样需要覆盖所有的实现方法
- 可以通过策略模式进行解决
24.2,基本介绍
- 策略模式(Strategy Pattern):定义算法族(策略组),分别封装起来,让算法之间可以相互替换,此模式让算法的变化可以独立于使用算法的客户
- 策略模式的算法组体现了几个设计原则
- 把变化的代码从不变的代码中抽离出来
- 针对接口编程而不是具体实现类编程
- 多用组合/聚合,少用继承
- 策略模式也是一种行为型模式
24.3,类图
Duck
:鸭子类顶层抽象类,也就是策略模式中的算法使用客户,不变的部分,通过聚合使用算法族,实现变化部分的具体行为XXXDuck
:鸭子类具体实现类,各自定义变化的算法族部分,有抽象类实现调用FlyBehaviour
:飞行策略顶层接口,算法族的顶层接口,也就是策略模式中的算法,变化的部分XXXFlyBehaviour
:具体的飞行策略,也就是具体的算法,由算法使用客户进行选择使用
24.4,代码实现
-
Duck
:抽象鸭子类,抽象的算法使用客户package com.self.designmode.strategy; /** * 策略模式: 算法使用客户, 顶层抽象类 * @author PJ_ZHANG * @create 2020-12-17 23:13 **/ public abstract class Duck { /** * 飞行策略 */ private FlyBehaviour flyBehaviour; /** * 游泳方法, 可以提策略 */ public void swiming() { System.out.println("鸭子游泳"); } /** * 飞行方法 */ public void fly() { // 通过定义的策略执行相对应行为 if (null != flyBehaviour) { flyBehaviour.fly(); } } /** * 动态变更策略方式 * @param flyBehaviour */ public void setFlyBehaviour(FlyBehaviour flyBehaviour) { this.flyBehaviour = flyBehaviour; } }
-
WildDuck
:具体的鸭子类,即具体算法使用客户package com.self.designmode.strategy; /** * 策略模式: 算法使用客户, 具体实现类_野鸭子 * @author PJ_ZHANG * @create 2020-12-17 23:16 **/ public class WildDuck extends Duck { public WildDuck() { super.setFlyBehaviour(new GoodFlyBehaviour()); } }
-
ToyDuck
:具体鸭子类package com.self.designmode.strategy; /** * 策略模式: 算法使用客户, 具体实现类_玩具鸭子 * @author PJ_ZHANG * @create 2020-12-17 23:16 **/ public class ToyDuck extends Duck { public ToyDuck() { super.setFlyBehaviour(new NoFlyBehaviour()); } }
-
FlyBehaviour
:飞行策略顶层接口,即该算法族顶层接口package com.self.designmode.strategy; /** * 策略模式: 算法组, 飞行策略顶层接口 * @author PJ_ZHANG * @create 2020-12-17 23:14 **/ public interface FlyBehaviour { void fly(); }
-
GoodFlyBehaviour
:具体飞行策略实现类,即该算法族具体算法package com.self.designmode.strategy; /** * 策略模式: 具体飞行算法, 飞的挺好 * @author PJ_ZHANG * @create 2020-12-17 23:17 **/ public class GoodFlyBehaviour implements FlyBehaviour { @Override public void fly() { System.out.println("飞的挺好..."); } }
-
NoFlyBehavior
:具体飞行策略实现类package com.self.designmode.strategy; /** * 策略模式: 具体飞行算法, 不会飞 * @author PJ_ZHANG * @create 2020-12-17 23:17 **/ public class NoFlyBehaviour implements FlyBehaviour { @Override public void fly() { System.out.println("不会飞..."); } }
-
Client
:客户端package com.self.designmode.strategy; /** * 策略模式: 客户端 * @author PJ_ZHANG * @create 2020-12-17 23:18 **/ public class Client { public static void main(String[] args) { // 定义一个野鸭子 Duck duck = new WildDuck(); duck.fly(); // 定义一个玩具鸭子 Duck toyDuck = new ToyDuck(); toyDuck.fly(); // 动态变更野鸭子的策略 duck.setFlyBehaviour(new NoFlyBehaviour()); duck.fly(); } }
24.5,策略模式的注意事项和细节
- 策略模式的关键是:分析项目中变化的部分和不变的部分
- 策略模式的核心思想:多用组合和聚合,少用继承
- 体现了OCP原则,客户端增加一种行为不需要修改原有代码,只需要添加一种策略即可,并动态对客户的策略行为进行变更即可
- 提供了可以替换继承关系的办法:将策略算法封装为一个独立的
Strategy
,使得可以独立的进行改变,更易于切换、易于理解、易于扩展 - 策略模式对每一种策略行为都提供一套类结构,被每一种行为方式都提供一个实现类实现,如果行为及行为方式过多,势必会造成类爆炸