策略模式
定义了算法族,分别封装起来,让它 们之间可以互相替换,此模式让算法的变化独立于使用 算法的客户。
模拟鸭子应用
现在有一个系统可以生产各种类型的鸭子,这些鸭子都会游泳、呱呱叫,但每个鸭子的外观都略有不同。
目前次系统设计了一个鸭子超类,并且让各种鸭子继承次超类。
1 2 3 4 5 6 7 8 9 10 11 12 13
| public abstract class Duck {
void quack() { System.out.println("呱呱叫"); }
void swim() { System.out.println("会游泳"); }
abstract void display(); }
|
1 2 3 4 5 6 7 8
| class MallardDuck extends Duck {
@Override void display() { System.out.println("野鸭"); } }
|
需求变更:让鸭子会飞
1 2 3 4 5 6
| public abstract class Duck { void fly() { System.out.println("会飞"); } }
|
问题:并不是所有的鸭子都会飞如橡皮鸭
解决方案:给不会飞的鸭子覆盖fly()方法
1 2 3 4 5 6 7 8 9 10 11 12
| class RubberDuck extends Duck {
@Override void display() { System.out.println("橡皮鸭"); }
@Override void fly() { System.out.println("不会飞"); } }
|
如果需求继续变更会怎么样?
- 加入诱饵鸭,不会飞不会叫,只会游泳
- 加入xx鸭,只会飞
- …
当需求变化,加入的鸭子越来越多,鸭子的功能也越来越多,会变的怎么样?
当有需求变化时,会导致重复的代码越来越多,新增一个功能,要改变大量类。
思考为什么会出现这种情况?
最初设计的时候没能找到变化点,并且将变化点封装起来。
改造
飞行为接口和实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public interface FlyBehavior { void fly(); }
public class FlyNoWay implements FlyBehavior{ @Override public void fly() { System.out.println("我不会飞"); } }
public class FlyWithWings implements FlyBehavior{ @Override public void fly() { System.out.println("我会飞"); } }
|
叫行为接口和实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public interface QuackBehavior { void quack(); }
public class Quack implements QuackBehavior{ @Override public void quack() { System.out.println("咕咕叫"); } }
public class MuteQuack implements QuackBehavior{ @Override public void quack() { System.out.println("不会叫"); } }
|
鸭子超类和实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public abstract class Duck { FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {}
public abstract void display();
public void swim() { System.out.println("鸭子都会游泳"); }
public void performFly() { flyBehavior.fly(); }
public void performQuack() { quackBehavior.quack(); } }
public class MallarDuck extends Duck{
public MallarDuck() { this.flyBehavior = new FlyWithWings(); this.quackBehavior = new MuteQuack(); }
@Override public void display() { System.out.println("绿头鸭"); } }
|
运行
1 2 3 4 5 6 7 8 9
| public class App { public static void main(String[] args) { Duck mallard = new MallarDuck(); mallard.performFly(); mallard.performQuack(); mallard.display(); mallard.swim(); } }
|
设计原则
- 多用组合,少用继承。
- 针对接口编程,而不是针对实现 编程。