策略模式 定义了算法族,分别封装起来,让他们能够互相替换,此模式让算法的变化独立于使用算法的客户。java
策略模式的三要素:git
抽象策略角色: 策略类,一般由一个接口或者抽象类实现。github
具体策略角色:包装了相关的算法和行为。算法
环境角色:持有一个策略类的引用,最终给客户端调用。编程
提出问题:要求作出一套模拟鸭子的游戏,游戏中会出现各类鸭子,它们一边游泳,一边呱呱叫。cookie
分析:根据OO设计思想,无非就是使各类鸭子实现本身相应的功能便可,如鸭子游泳,鸭子呱呱叫。this
解决方案1.0:设计一个接口(Duck),而后根据须要完成不一样的实现,如红头鸭,绿头鸭。。。。设计
public interface Duck { public abstract void quack(); public abstract void swim(); public abstract void display(); } public MallardDuck implements Duck{ public abstract void quack(){ System.out.println("呱呱~~"); } public abstract void swim(){ System.out.println("欢快的游泳~~"); } public abstract void display(){ System.out.println("绿头鸭~~"); } } public RedHeadDuck implements Duck{ public abstract void quack(){ System.out.println("呱呱~~"); } public abstract void swim(){ System.out.println("欢快的游泳~~"); } public abstract void display(){ System.out.println("红头鸭~~"); } }
忽然增长一个新的需求,要求有野鸭,除了具备这两个功能外,还会飞(fly),同时还有一种橡皮鸭,叫声时吱吱。。code
此时该方案便暴露了一下缺点。。。。orm
缺点:牵一发而动全身,咱们很难知道全部鸭子的行为,当针对有些实现须要添加新的功能时
解决方案1.1
为了更加灵活,面向接口编程。
public interface Flyable { public abstract void fly(); } public interface Swimable { public abstract void swim(); } public interface Quackable { public abstract void quack(); } public RedHeadDuck implements Quackable implements Swimable {...} public WildDuck implements Quackable implements Swimable implements Flyable {...}
若是有一万种鸭子,这种方式简直不敢想象,重复代码太多!
解决方案2.0
采用策咯模式解决此问题。
step1:把会变化的部分取出来,并封装起来,好让其余代码不受影响。
step2:封装行为的大局观
step3:代码实现
抽象策略角色
// 飞行行为 public interface FlyBehavior { public abstract void fly(); } // 叫声行为 public interface QuackBehavior { public abstract void quack(); }
具体策略对象
// 橡皮鸭叫 public RubberDuckBehavior implements QuackBehavior { public void quack(){ System.out.println("吱吱~~"); } } // 野鸭叫 public WildDuckBehavior implements QuackBehavior { public void quack(){ System.out.println("嘎嘎~~"); } } // 大黄鸭叫 public YellowDuckBehavior implements QuackBehavior { public void quack(){ System.out.println("呱呱~~"); } }
// 不会飞 public class FlyNoWay implements FlyBehavior { public void fly(){ System.out.println("不会飞~~"); } } // 用翅膀飞 public class FlyWithWings implements FlyBehavior { public void fly(){ System.out.println("用翅膀飞~~"); } } // 螺旋桨飞 public class FlyLikePlane implements FlyBehavior { public void fly(){ System.out.println("用螺旋桨~~"); } }
环境角色
抽象类
public abstract class Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; // 动态设定行为 public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; } public void performFly() { flyBehavior.fly(); } public void performQuack() { quackBehavior.quack(); } public abstract void display(); public void swim() { System.out.println("鸭子天生会游泳!"); } }
实现
public class WildDuck extends Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; public WildDuck() { // 默认会飞,野鸭叫嘎嘎 this.flyBehavior = new FlyWithWings(); this.quackBehavior = new WildDuckBehavior(); } // 动态设定行为 public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; } public void performFly() { flyBehavior.fly(); } public void performQuack() { quackBehavior.quack(); } public void display(){ System.out.println("这是一只野鸭"); }; public void swim() { System.out.println("鸭子天生会游泳!"); } }
需求改变:野鸭的翅膀受伤,不会飞了
public static void main(String[] args) { Duck duck = new WildDuck(); duck.setFlyBehavior(new FlyNoWay()); duck.performFly();// 输出:不会飞~~ }
需改改变:新增一只火箭鸭,能飞到太空,不会游泳,外形像火箭同样,叫嘎嘎
public RocketDuckFlyBehavior implements FlyBehavior { public void fly(){ System.out.println("飞到太空~~"); } }
public class RocketDuck extends Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; public WildDuck() { // 默认会飞,野鸭叫嘎嘎 this.flyBehavior = new RocketDuckFlyBehavior(); this.quackBehavior = new WildDuckQuackBehavior(); } // 动态设定行为 public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; } public void performFly() { flyBehavior.fly(); } public void performQuack() { quackBehavior.quack(); } public abstract display() { System.out.println("外形像火箭~~"); } public void swim() { System.out.println("不会游泳"); } }
优势:
1.策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承能够把代码转移到符类,从而避免重复代码 。
2.在策略模式中利用组合和委托来让环境角色拥有执行算法的能力,这也是继承的一种更轻便的替代方案。
3.提供了对开放—封闭原则的完美支持,将算法封装在独立的strategy中,使得它们易于切换,易于理解,易于扩展
4.利用组合、委托和多态等技术和思想,能够有效地避免多重条件选择语句
缺点:
1.客户端必须知道全部的策略类,区分他们之间的区别,并自行决定使用哪个策略类。
2.针对每一种行为状况须要建立一个策略类,形成不少的策略类。
我的站点地址:www.mycookies.cn(适合java初学者的我的博客项目) github:https://github.com/liqianggh/blog