以Head First设计模式中第一章给出的鸭子例子来讲,此例子中有个鸭子的类,一共有普通鸭、模型鸭和玩具鸭三种。区别是普通鸭可以飞行并发出嘎嘎的叫声;模型鸭不能飞行且不能发声;玩具鸭不能飞行,但可以依靠火箭推进飞行(^..^就是这么吊)且发出吱吱的声音。面对这些有类似的属性但不同的行为的类来说,使用策略模式便有利于类的拓展,其原则是:多用组合,少用继承。简单的思路是:定义算法族,分别封装起来,让它们相互之间可以替换,使算法的变化独立于使用算法的客户。以下就从实例来说明:
首先是鸭子类,那就创建一个鸭子的超类(Duck),鸭子有飞行和鸣叫的行为,所以其下有两个方法用于执行其飞行行为(performFly)和鸣叫行为(performQuack),当然可以添加一些其他方法(display)。
Duck类
/**
* 鸭子的超类
*/
public abstract class Duck {
public Duck() {
// 执行鸭子的特征
display();
}
//鸭子的外观,所有的鸭子外观都不一样,需要实例化的时候自定这只鸭子是长什么样的
public abstract void display();
//执行鸭子的飞行行为
public void performFly(){
}
//执行鸭子的鸣叫行为
public void performFly(){
}
}
可能此处会想到直接创建三种鸭子子类来继承Duck超类,然后重写performFly()和performFly()方法。如果这么做的话要是再出现一种鸭子可以飞行但是发出吱吱的叫声那就会和普通鸭子的飞行行为一样,这样就需要重写写一遍飞行的代码而没有起到最初的代码复用的情况。所以此处考虑到一个设计原则,就是找出应用中可能需要变化的地方把它独立出来,因此采用接口的方式设计飞行行为接口(FlyBehavior)和鸣叫接口(QuackBehavior)
/**
* 鸭子的飞行行为接口,所有的飞行行为类需实现这个接口
*/
public interface FlyBehavior {
//实现并赋予飞行行为
public void fly();
}
/**
* 同样鸭子具有叫的行为
*/
public interface QuackBehavior {
//实现并赋予鸣叫行为
public void quack();
}
既然有了飞行和鸣叫的接口,那就需要实现其具体的行为,因此再创建所有的行为类实现它们,当然可以添加其他的飞行行为和鸣叫行为
可飞行的行为类:
/**
* 可飞行
*/