《Head First 设计模式》笔记1-策略模式
定义
策略模式定义了算法族,分别封装起来,让它们之间可以互换替换,此模式让算法的变化独立使用算法的客户。
书中鸭子的例子
使用继承的方法
如果有新的需求,需要实现 fly() 方法,使用继承的方法会在 Duck 中加入 fly() 方法,不过并不是所有的鸭子都会飞,比如橡皮鸭子;这会导致下列缺点:
- 代码在多个子类中重复;
- 运行时的行为不容易改变;
- 很难知道所有鸭子的全部行为;
- 改变会牵一发而动全身,造成其他鸭子不想要的改变;
利用接口实现
这将导致一个问题,虽然 Flyable 和 Quackable 可以解决问题,但是代码不能复用;
使用策略模式
分类变化的部分:将 fly 和 quack 的动作从基类 Duck 中分离出来。
利用接口代替每个行为:定义 FlyBehavior 与 QuackBehavior 行为接口,鸭子类并不实现这些接口,是由我们创造一组其他类专门实现 FlyBehavior 与 QuackBehavior。
这样的设计,可以让各种 fly 和 quack 的动作被其他的对象复用,并且新增行为也不会影响到既有行为。
QuackBehavior 接口
interface QuackBehavior {
void quack();
}
FlyBehavior接口
interface FlyBehavior {
void fly();
}
QuackBehavior 具体行为
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("Silence");
}
}
public class Gua implements QuackBehavior {
public void quack() {
System.out.println("Gua Gua Gua~~");
}
}
FlyBehavior 具体行为
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("fly fly fly~~~");
}
}
public class FlyNoWay implements FlyBehavior {
public void fly() {
// do nothing
}
}
现在鸭子会将飞行和呱呱叫的动作“委托”给 FlyBehavior 和 QuackBehavior 处理,我们在 Duck 中增加两个方法 performFly()
,performQuack()
public abstract class Duck {
Duck() {}
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;
public abstract void display();
public void swim() {
System.out.println("all ducks can swim");
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
在每种鸭子继承超类 Duck 的时候,只需要在构造函数中设置对应的 FlyBehavior 和 QuackBehavior 实例变量即可。如果需要动态的修改,只需要在 Duck 中 setter 方法即可。
public class RedHeadDuck extends Duck {
RedHeadDuck() {
quackBehavior = new Gua();
flyBehavior = new FlyWithWings();
}
@Override
public void display() {
System.out.println("This is RedHeadDuck");
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
优缺点
http://www.cnblogs.com/wolf-sun/p/3534573.html
优点:
- 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码。
- 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
- 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
缺点:
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
- 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com
文章标题:《Head First 设计模式》笔记1-策略模式
文章字数:1.1k
本文作者:Bin
发布时间:2018-06-25, 23:38:06
最后更新:2019-08-06, 00:07:35
原始链接:http://coolview.github.io/2018/06/25/Head-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E3%80%8AHead-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E3%80%8B%E7%AC%94%E8%AE%B01-%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。