策略模式将可变的部分从程序中抽象分离成算法接口,在该接口下分别封装一系列算法实现,并使它们可以互相替换,从而导致客户端程序独立于算法的改变。
复合优先于继承,多用组合,少用继承
在类中增加一个私有域,引用另一个已有的类的实例,通过调用引用实例的方法从而获得新的功能,这种设计被称作组合。
组合:将飞行行为抽象为接口,在父类中持有该接口,并由该接口代替飞行行为
面向接口编程,而不是面向实现编程
多用组合,少用继承
策略模式的实现
- 通过分离变化得出策略接口Strategy
- Strategy的实现类
- 客户程序有一个Strategy
- 在客户程序中选择/组装正确的Strategy实现
策略模式优点
- 使用了组合,是架构更加灵活
- 富有弹性,可以较好的对应变化(开-闭原则)
- 更好的代码复用性(相对于继承)
- 消除大量的条件语句
策略模式缺点
- 客户代码需要了解每个策略实现的细节
- 增加了对象的数目
策略模式的适用场景
- 许多相关的类仅仅是行为差异
- 运行时选取不同的算法变体
- 通过条件语句在多个分支中选取一
鸭子代码实现策略模式示例

1 /** 2 * 超类,所有的鸭子都有继承此类 3 * 抽象了鸭子的行为:显示和鸣叫 4 * */ 5 public abstract class Duck { 6 /* 7 * 鸭子发出叫声 8 * 通用行为,由超类实现 9 * */ 10 public void quack(){ 11 System.out.println("嘎嘎。。。。"); 12 } 13 /* 14 * 显示鸭子的外观 15 * 鸭子的外观各不相同,声明外abstract,由子类实现**/ 16 public abstract void display(); 17 18 /** 组合:将飞行行为抽象为接口,在父类中持有该接口,并由该接口代替飞行行为*/ 19 @SuppressWarnings("unused") 20 private FlyingStragety flyingStragety; 21 public void setFlyingStragety(FlyingStragety flyingStragety){ 22 this.flyingStragety = flyingStragety; 23 } 24 public void fly(){ 25 flyingStragety.performFly(); 26 } 27 }

1 /** 2 * 策略接口,实现鸭子的飞行行为 3 **/ 4 public interface FlyingStragety { 5 void performFly(); 6 }

1 public class FlyWithRocket implements FlyingStragety{ 2 @Override 3 public void performFly() { 4 System.out.println("我用火箭飞行"); 5 } 6 } 7 public class FlyWithWin implements FlyingStragety{ 8 @Override 9 public void performFly() { 10 System.out.println("振翅高飞"); 11 } 12 } 13 public class FlyNoWay implements FlyingStragety{ 14 @Override 15 public void performFly() { 16 System.out.println("我不会飞行"); 17 } 18 }

1 public class MallardDuck extends Duck{ 2 public MallardDuck(){ 3 super(); 4 super.setFlyingStragety(new FlyWithWin()); 5 } 6 @Override 7 public void display() { 8 System.out.println("我的脖子是绿色的"); 9 } 10 } 11 public class RedheadDuck extends Duck{ 12 13 public RedheadDuck(){ 14 super(); 15 super.setFlyingStragety(new FlyWithWin()); 16 } 17 @Override 18 public void display() { 19 System.out.println("我的头是红色的"); 20 } 21 } 22 public class SpaceDuck extends Duck{ 23 public SpaceDuck(){ 24 super(); 25 super.setFlyingStragety(new FlyWithRocket()); 26 } 27 @Override 28 public void display() { 29 System.out.println("我是太空鸭子"); 30 } 31 public void quack() { 32 System.out.println("无线电通讯"); 33 } 34 } 35 public class RubberDuck extends Duck{ 36 public RubberDuck(){ 37 super();//调用父类的构造函数 38 super.setFlyingStragety(new FlyNoWay()); 39 } 40 @Override 41 public void display() { 42 System.out.println("我的橡胶鸭子"); 43 } 44 public void quack() { 45 System.out.println("瑟瑟。。。"); 46 } 47 } 48 public class BigYellowDuck extends Duck{ 49 public BigYellowDuck(){ 50 super(); 51 super.setFlyingStragety(new FlyNoWay()); 52 } 53 @Override 54 public void display() { 55 System.out.println("我是大黄鸭子"); 56 } 57 public void quack() { 58 } 59 }

1 public class Test { 2 public static void main(String[] args) { 3 Duck duck =null; 4 duck = new MallardDuck(); 5 duck.display(); 6 duck.quack(); 7 duck.fly(); 8 System.out.println("**************"); 9 duck = new RedheadDuck(); 10 duck.display(); 11 duck.quack(); 12 duck.fly(); 13 System.out.println("*****************"); 14 duck = new RubberDuck(); 15 duck.display(); 16 duck.quack(); 17 duck.fly(); 18 System.out.println("*****************"); 19 duck = new BigYellowDuck(); 20 duck.display(); 21 duck.quack(); 22 duck.fly(); 23 System.out.println("*****************"); 24 duck = new SpaceDuck(); 25 duck.display(); 26 duck.quack(); 27 duck.fly(); 28 } 29 }