前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式 | 行为型 | 策略模式

设计模式 | 行为型 | 策略模式

作者头像
被水淹没
发布2023-02-25 19:14:34
3270
发布2023-02-25 19:14:34
举报
文章被收录于专栏:迈向架构师

策略模式(Strategy)

策略模式(Strategy)

介绍

策略模式是一种行为设计模式。

策略模式定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。使算法的变化独立于使用它们的客户端。

适用场景

  • 想使用对象中各种不同的算法变体,并希望能在运行时切换算法
  • 将类的业务逻辑与其算法实现隔离开。
  • 有许多仅在执行某些行为时略有不同的相似类。
  • 当类中使用了复杂条件运算符以在同一算法的不同变体中切换(冗长的分支判断)。
  • ...

优缺点

优点:

  • 可以在运行时切换对象内的算法。
  • 可以将算法的实现和使用算法的代码隔离开来。
  • 可以使用组合来代替继承。
  • 开闭原则:无须修改上下文即可引入新策略。

缺点:

  • 复杂度增加。
  • 客户端必须知晓策略间的不同。

与其他模式的关系

  • 装饰模式可让你更改对象的外表,策略模式则让你能够改变其本质。
  • 模板方法模式与策略模式:
    • 模板方法基于继承机制:它允许通过扩展子类中的部分内容来改变部分算法。
    • 策略基于组合机制:可以通过对相应行为提供不同的策略来改变对象的部分行为。
    • 模板方法在类层次上运作,因此它是静态的。
    • 策略在对象层次上运作,因此允许在运行时切换行为。
  • 观察者模式是解耦观察者和被观察者。策略模式跟两者类似,它解耦的是策略的定义、创建、使用这三部分。

实现方式

  1. 声明该算法所有变体的通用策略接口
  2. 将算法逐一抽取到各自的类中,它们都必须实现策略接口
  3. 在上下文类中添加一个成员变量用于保存对于策略对象的引用。然后提供设置器以修改该成员变量。
    • 上下文仅可通过策略接口同策略对象进行交互。
    • 如有需要还可定义一个接口来让策略访问其数据。

Java 8 开始支持 lambda 方法, 它可作为一种替代策略模式的简单方式。


示例

策略接口

代码语言:javascript
复制
public interface Strategy {
    // 声明该算法所有变体的通用策略接口。
    void evict();
}

策略实现

代码语言:javascript
复制
public class StrategyFIFO implements Strategy {
    // 将算法逐一抽取到各自的类中,它们都必须实现策略接口。
    @Override
    public void evict() {
        System.out.println("使用【先进先出】策略进行丢弃");
    }
}

public class StrategyLRU implements Strategy {
    @Override
    public void evict() {
        System.out.println("使用【最近最久未使用】策略进行丢弃");
    }
}

public class StrategyLFU implements Strategy {
    @Override
    public void evict() {
        System.out.println("使用【最近最少使用】策略进行丢弃");
    }
}

Context 上下文

代码语言:javascript
复制
public class Cache {

    private Map cacheData = new HashMap<>();

    // 在上下文类中添加一个成员变量用于保存对于策略对象的引用。
    private Strategy evictionStrategy;

    // 提供设置器以修改该成员变量。
    public void setEvictionStrategy(Strategy evictionStrategy) {
        this.evictionStrategy = evictionStrategy;
    }

    // 通过策略接口同策略对象进行交互
    public void evict() {
        evictionStrategy.evict();
    }

    public void add(String value) {
        // ...
    }
    public String get() {
        // ...
        return null;
    }
}

测试代码

代码语言:javascript
复制
public class StrategyTest {
    @Test
    public void test() {
        Cache cache = new Cache();
        cache.add("添加");
        cache.add("缓存");
        cache.add("数据");

        cache.setEvictionStrategy(new StrategyFIFO());
        cache.get();
        cache.evict();
        cache.evict();

        cache.setEvictionStrategy(new StrategyLRU());
        cache.evict();

        cache.setEvictionStrategy(new StrategyLFU());
        cache.evict();
    }
}

实例

JDK

Comparator

java.util.Comparator 是策略接口类

Comparator.compare() 是策略方法

Collections.sort(List list, Comparator c) 调用自定义策略

以上代码与文章会同步到 github 仓库:

/chenbihao/Design-Patterns

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 迈向架构师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 策略模式(Strategy)
    • 介绍
      • 适用场景
        • 优缺点
          • 与其他模式的关系
            • 实现方式
              • 示例
                • 实例
                  • JDK
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档