策略模式

2019-01-04 2791 ℃

定义

策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

结构

  • 环境类(Context): 也叫上下文,对策略进行二次封装,目的是避免高层模块对策略的直接调用。
  • 抽象策略(Strategy): 通常情况下为一个接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装这部分公共的代码。
  • 具体策略(ConcreteStrategy): 具体策略角色通常由一组封装了算法的类来担任,这些类之间可以根据需要自由替换。

策略模式UML类图

优点

  • 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
  • 策略模式提供了管理相关的算法族的办法,算法之间可以自由切换。
  • 策略模式提供了可以替换继承关系的办法。
  • 使用策略模式可以避免使用多重条件,如果不使用策略模式,对于所有的算法,必须使用条件语句进行连接,通过条件判断来决定使用哪一种算法。

缺点

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
  • 策略模式将会产生很多策略类,导致策略膨胀。

适用场景

  • 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
  • 一个系统需要动态地在几种算法中选择一种。
  • 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
  • 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。

代码实现

设计一只鸭子,它可以动态地改变叫声,鸭子的叫声就是算法族。

叫声接口(抽象策略)

public interface QuackBehavior { /** * 发出叫声的方法 */ void quack(); }

叫声的实现类(具体策略)

public class Quack implements QuackBehavior { @Override public void quack() { System.out.println("嘎嘎叫"); } }
public class Squeak implements QuackBehavior { @Override public void quack() { System.out.println("吱吱叫"); } }

鸭子类(环境类)

public class Duck { private QuackBehavior quackBehavior; /** * 鸭子的构造方法 * @param qb 选择的策略 */ public Duck(QuackBehavior qb){ this.quackBehavior=qb; } /** * 执行策略的方法 */ public void performQuack() { quackBehavior.quack(); } /** * 替换策略的方法 * @param qb 新策略 */ public void setQuackBehavior(QuackBehavior qb) { this.quackBehavior = qb; } }

执行策略

public class Test { public static void main(String[] args) { // 执行第一种策略,发出嘎嘎叫 Duck duck = new Duck(new Quack()); duck.performQuack(); // 执行第二种策略,替换掉原策略,发出吱吱叫 duck.setQuackBehavior(new Squeak()); duck.performQuack(); } }

输出结果

嘎嘎叫
吱吱叫
版权声明:周华个人博客原创文章,转载请注明出处。

文章链接:http://www.iszhouhua.com/strategy-pattern.html

发表时间:2019-01-04 22:20

最后更新时间:2019-01-27 17:41