HeadFirst --策略模式
本来是要做一个鸭子应用的:
1. 很容易想到用继承, Duck基类中有很多方法,子类只要重写父类方法即可;
这样有些问题:比如基类中增加一个方法fly ,那么所有的子类都有了fly()方法,但是并不是需要所有的子类都有这个方法的。
extends 只要是抽象方法,都是要求子类去实现的,每增加一个子类就要被迫去实现 父类所有方法。
为了避免这样的问题,我们很容易想到用接口实现,只要实现接口中,你需要的方法即可
这个实现方法,确实可以避免每个子类都要去实现基类的方法,但是也引入了一个新的问题
啥问题呢? 无法复用基类的代码,如果只要稍微改动接口中的某个方法,那么所有的子类可能都需要修改。
这是从一个坑跳到另外一个坑, 不是特别好的设计。
设计原则1 :
找出应用中需要变化之处,将他们独立出来,不要和那些不需要的变化的代码放在一块。
设计原则2:
针对接口编程,而不是针对实现编程。
也就是说,鸭子的行为被放在分开的类中,此类专门提供某行为接口的实现。
针对接口编程,其实是针对超类型编程
上图中可以看到:
//面向实现编程 Dog dog = new Dog(); //面向接口编程 Amimal animal = new Dog(); animal.makeSound(); // 更高级一些,子类实例化不需要硬编码,而是运行时 才指定实际的对象 a = getAnimal(); a.makesound();可以清楚看到面向实现编程和面向接口编程的区别。
行为类都单独抽取出来一个接口,一个FlyBehavior 和一个QuackBehavior 。
鸭子类继承Duck;
飞行行为实现FlyBehavior,呱呱行为QuackBehavior接口
设计原则 3:
多用组合,少用继承
下面看下具体实现代码
定义一个鸭子:
package designPattern.strategy; public abstract class Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; public Duck() { } public void setFlyBehavior (FlyBehavior fb) { flyBehavior = fb; } public void setQuackBehavior(QuackBehavior qb) { quackBehavior = qb; } abstract void display(); public void performFly() { flyBehavior.fly(); } public void performQuack() { quackBehavior.quack(); } public void swim() { System.out.println("All ducks float, even decoys!"); } }
两个行为类接口:
package designPattern.strategy; public interface QuackBehavior { public void quack(); }
package designPattern.strategy; /** * * @author wangxiaoming * 定义一个基本行为接口 */ public interface FlyBehavior { public void fly(); }
然后你想实现哪种行为类的就去实现这个行为类的接口,继承鸭子基类,用get set方法定义鸭子行为,即可实现,你想要怎样的鸭子都行,能飞的,不能飞的,能叫的,不能叫的。
package designPattern.strategy; public class FlyWithWings implements FlyBehavior { @Override public void fly() { System.out.println("I am Flying"); } }
package designPattern.strategy; public class MuteQuack implements QuackBehavior { @Override public void quack() { System.out.println("<< Slience >>"); } }
看模拟器:
package designPattern.strategy; public class MiniDuckSimulator1 { /** * * @param args * 啥叫用组合方式 这里面的FlyBehavior 和QuackBehavior 其实就是组合 不同的行为组合起来 * 而不是说鸭子有这两个行为然后继承即可,也就是说有一个会比是一个 好。 */ public static void main(String[] args){ // 高级一些的实现方式 Duck mallard = new MallardDuck(); mallard.setFlyBehavior(new FlyWithWings()); mallard.performQuack(); mallard.performFly(); Duck model = new ModelDuck(); model.performFly(); model.setFlyBehavior(new FlyRocketPowered()); model.performFly(); } }
package designPattern.strategy; public class MallardDuck extends Duck { public MallardDuck() { quackBehavior = new Quack(); flyBehavior = new FlyWithWings(); } public void display() { System.out.println("I'm a real Mallard duck"); } }
package designPattern.strategy; /** * * @author wangxiaoming * 模型鸭,不能飞 */ public class ModelDuck extends Duck { public ModelDuck() { flyBehavior = new FlyNoWay(); quackBehavior = new Quack(); } public void display() { System.out.println("I'm a model duck"); } }