策略模式
模拟鸭子应用
使用继承实现
使用一个父类,所有的子类都继承其父类以实现鸭子的一些共同行为
//鸭子的父类,所有的鸭子都实现该父类
public class Duck {
//鸭子呱呱叫方法
public void quack(){}
//鸭子会游泳
public void swim(){}
//展示方法
public void display(){}
}
如果想让鸭子都能飞,直接在父类中加入一个fly()方法,则所有的鸭子都会飞。
但是实际上有一些鸭子(橡胶鸭)并不会飞。由于继承而导致“复用”非常麻烦。
在每种不会飞的鸭子的子类中,都必须覆盖掉父类的fly()方法。
quack()方法也类似。
使用接口实现
把飞行的行为和叫的行为都提取为接口
public interface Quackable{
public void quack();
}
public interface flyable{
public void fly();
}
把需要实现fly()和需要实现quack()行为的鸭子,则实现对应的接口即可。
这种方式会解决不会飞的鸭子(橡胶鸭)没有fly()的问题,但是这种方式会造成代码无法复用,使重复代码增多。
即如果有许多的鸭子需要修改fly()的行为,则一下子要修改许许多多的代码。
使用设计原则
设计原则:封装变化
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
设计原则:针对接口编程,而不是针对实现编程(针对超类型编程)
如果使用2个类的具体实现去实现提取出来的行为,那么在改变鸭子的行为时,会被绑的死死的,除非写更多的代码。
所以使用2个父类来代表每个行为,再在使用时使用setter方法赋予其行为
设计原则:多用组合,少用继承
最终整合代码:
//鸭子父类
public abstract class Duck{
//为行为接口类型声明两个引用变量,所有的鸭子子类都继承他们
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public abstract void display();
//把行为委托给行为类
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
public void swim(){
System.out.println("All duck float, even decoys");
}
//省略FlyBehavior、QuackBehavior的setter方法
}
//以fly为例子,这是所有飞行行为类必须实现的接口
public interface FlyBehavior{
public void fly();
}
//这是飞行行为的实现
public class FlayNoway implements FlyBehavior{
public void fly(){
System.out.println("I can't fly.");
}
}
public class FlyWithWings implements FlyBehavior{
public void fly(){
System.out.println("I can fly.");
}
}
//省略MallardDuck类的实现
//main方法
public static void main(String[] args){
Duck mallard = bew MallardDuck();
mallard.performFly();
//改变鸭子的飞行行为
mallard.setFlyBehavior(new 新的飞行行为类());
mallard.performFly();
}
策略模式的定义
定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。