策略模式定义
策略模式(Strategy Pattern)的定义:该模式定义了一系列算法(行为),并将每个算法封装起来,使它们可以相互替换。
策略模式是一种对象行为型模式,它通过对算法(行为)进行封装,把使用算法的抽象和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
策略模式的代码实现
我们参考《Head First 设计模式》设计的一个场景:模拟鸭子游戏。在这个游戏里有各种各样的鸭子,野鸭,橡皮鸭,木头鸭……等等,
- 我们首先定义一个父类Duck,有了鸭子才会有鸭子的行为,在策略模式里这个类叫Context(环境类);
- 找出所有鸭子的共同行为(算法):飞(fly),游泳(swim),呱呱叫(quack)……等等,我们将这些算法设计成公共接口,即抽象策略(Strategy)类,
- 具体行为去实现这些接口,即具体策略(Concrete Strategy)类,比如,飞的行为有:用翅膀飞,不会飞,叫的行为有:呱呱叫,吱吱叫……等等
具体代码在见文章最后
策略模式的应用场景
- 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。
- 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
- 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。
策略模式的优缺点
策略模式的优点
- 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句。if…else…
- 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
- 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
- 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
- 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。
策略模式的缺点
- 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
- 策略模式造成很多的策略类
Duck类
public abstract class Duck {
Flybehavior flybehavior;
Quackbehavior quackbehavior;
public Duck() {}
public Flybehavior getFlybehavior() {
return flybehavior;
}
public void setFlybehavior(Flybehavior flybehavior) {
this.flybehavior = flybehavior;
}
public Quackbehavior getQuackbehavior() {
return quackbehavior;
}
public void setQuackbehavior(Quackbehavior quackbehavior) {
this.quackbehavior = quackbehavior;
}
public abstract void display();
public void performFly() {
flybehavior.fly();
}
public void performQuack() {
quackbehavior.quack();
}
}
抽象策略类
public interface Flybehavior {
void fly();
}
具体策略类
public class FlyWithWings implements Flybehavior {
@Override
public void fly() {
System.out.println("fly");
}
}
public class FlyNoWay implements Flybehavior {
@Override
public void fly() {
System.out.println("cannot fly");
}
}
抽象策略类
public interface Quackbehavior {
void quack();
}
具体策略类
public class Quack implements Quackbehavior {
@Override
public void quack() {
System.out.println("呱呱叫");
}
}
public class MateQuack implements Quackbehavior {
@Override
public void quack() {
System.out.println("silence");
}
}
Duck实现类
public class MallardDuck extends Duck {
public MallardDuck() {
flybehavior = new FlyWithWings();
quackbehavior = new Quack();
}
@Override
public void display() {
System.out.println("野鸭");
}
}
行为调用
public class MiniDuckSimulator {
public static void main(String[] args) {
Duck duck = new MallardDuck();
duck.performFly();
duck.performQuack();
//更换算法(行为)
duck.setFlybehavior(new FlyNoWay());
duck.performFly();
}
}
调用结果
fly
呱呱叫
cannot fly
Process finished with exit code 0