设计模式(14):策略模式

「尺有所短,寸有所长;不忘初心,方得始终。」

一、策略模式是什么

策略模式「定义了一系列算法,并将每个算法封装起来,使他们可以在运行时相互替换,且算法的变化不会影响到使用算法的客户」。属于行为型模式。

「主要作用」:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

「主要解决」:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。

「何时使用」:一个系统有许多许多类,而区分它们的只是他们直接的行为。

「如何解决」:将这些算法封装成一个一个的类,任意地替换。

「关键代码」:实现同一个接口

设计模式(14):策略模式

需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数。

策略模式定义和封装了一系列的算法,它们是可以相互替换的,也就是说它们具有共性,而它们的共性就体现在策略接口的行为上,另外为了达到最后一句话的目的,也就是说让算法独立于使用它的客户而独立变化,我们需要让客户端依赖于策略接口。

一种很简单的解释,「在我们的开发过程中,经常会遇到大量的if…else或者switch…case语句,当这些语句在开发中只是为了起到分流作用,这些分流和业务逻辑无关,那么这个时候就可以考虑用策略模式」

二、策略模式的适用场景

  • 当想使用对象中各种不同的算法变体,并希望能在运行时切换算法时, 可使用策略模式。
  • 当有许多仅在执行某些行为时略有不同的相似类时, 可使用策略模式。
  • 如果算法在上下文的逻辑中不是特别重要,使用策略模式能将类的业务逻辑与其算法实现细节隔离开来。
  • 当类中使用了复杂条件运算符以在同一算法的不同变体中切换时, 可使用策略模式。

「在开发过程中,经常会遇到大量的if…else或者switch…case语句,当这些语句在开发中只是为了起到分流作用,这些分流和业务逻辑无关,那么这个时候就可以考虑用策略模式」

三、策略模式结构

  • 「上下文(Context)角色」:持有一个维护指向具体策略的引用, 且仅通过策略接口与该对象进行交流。

  • 「抽象策略(Strategy)角色」:通常由一个接口或抽象类实现。声明了一个上下文用于执行策略的方法。

  • 「具体策略(ConcreteStrategy)角色」:实现了上下文所用算法的各种不同变体。

  • 「客户端」 :创建一个特定策略对象并将其传递给上下文。上下文则会提供一个设置器以便客户端在运行时替换相关联的策略。

设计模式(14):策略模式

四、策略模式实现方式

  • 创建一个策略接口,声明算法所有变体的通用接口方法。
  • 创建各个算法类并且实现策略接口。
  • 在上下文中添加一个成员变量用于保存对于策略对象的引用。然后提供设置器以修改该成员变量。上下文仅可通过策略接口同策略对象进行交互。
  • 客户端必须将上下文类与相应策略进行关联, 使上下文可以预期的方式完成其主要工作。

五、策略模式的实现

  • 「抽象策略角色实现」

    /**
    * 抽象策略角色: 定义所有支持的算法的公共接口
    */

    public interface Strategy {


    public String methodA();

    public String methodB();

    }
  • 「具体策略角色实现」

    /**
    * 具体策略 :A 策略
    */

    public class AStrategy implements Strategy {
    @Override
    public String methodA() {
    return "策略A 的methodA";
    }

    @Override
    public String methodB() {
    return "策略A 的methodB";
    }
    }

    /**
    * 具体策略 :B 策略
    */

    public class BStrategy implements Strategy {
    @Override
    public String methodA() {
    return "策略B 的methodA";
    }

    @Override
    public String methodB() {
    return "策略B 的methodB";
    }
    }
  • 「上下文角色实现」

    /**
    * 上下文角色 :维护指向具体策略的引用
    */

    public class Context {

    private Strategy Strategy;

    public Context(Strategy Strategy) {
    this.Strategy = Strategy;
    }

    public String methodA() {
    return Strategy.methodA();
    }

    public String methodB() {
    return Strategy.methodB();
    }

    }
  • 「客户端代码实现」

    public static void main(String[] args) {
    Context context = new Context(new BStrategy());
    System.out.println(context.methodA());
    System.out.println(context.methodB());
    }

六、策略模式和简单工厂模式的结合

  • 「上下文角色实现」

    /**
    * 上下文角色
    */

    public class Context {

    private Strategy strategy;

    public Context(String type) {
    switch (type){
    case "A":
    this.strategy = new AStrategy();
    break;
    case "B":
    this.strategy = new AStrategy();
    break;
    }
    }

    public String methodA() {
    return strategy.methodA();
    }

    public String methodB() {
    return strategy.methodB();
    }

    }
  • 「客户端代码实现」

    public static void main(String[] args) {
    Context context = new Context("A");
    System.out.println(context.methodA());
    System.out.println(context.methodB());
    }

「策略模式和简单工厂模式的结合后,客户端只需要知道Context一个类,降低了耦合性。」

六、策略模式的优缺点

「优点:」

  • 结构清晰,把策略分离成一个个单独的类,使得程序更清晰。
  • 代码耦合度降低,安全性提高。

「缺点:」

  • 客户端必须要知道所有的策略类,才能确定使用那个策略,所以策略模式适用于提前知道所有策略的情况下。
  • 策略类数量增多,增加算法,需要新增策略类。

七、策略模式和简单工厂模式的区别

  • 策略模式和简单工厂模式都是通过多态来实现不同子类的选取。
  • 在简单工厂模式中实现了通过条件选取一个类去实例化对象,策略模式则将选取相应对象的工作交给模式的使用者,它本身不去做选取工作。
    • 简单工厂模式中只需要传递相应的条件就能得到想要的一个对象,然后通过这个对象实现算法的操作
    • 策略模式使用时必须首先创建策略对象作为参数传递进去,通过该对象调用不同的算法。

八、总结

策略模式,「实质是对算法的封装 , 它把算法的责任和算法本身分割开 , 委派给不同的对象管理」,用户可以自由选择这些算法进行操作。策略模式本身理解起来没什么难点,但是在实际应用中其本身主要结合工厂模式一起使用。


原文始发于微信公众号(星河之码):设计模式(14):策略模式

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/27136.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!