设计模式笔记_行为型_策略模式

1. 策略模式介绍

策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以互换。这种模式使得算法可以在不影响客户端的情况下发生变化。

类比场景:可以将策略模式类比为选择出行方式的场景。假设你要从一个城市到另一个城市,你可以选择不同的出行方式,比如开车、坐火车、或者乘飞机。每种方式都有自己的优缺点,但最终目的是到达目的地。策略模式就像是为你提供了一种机制来选择最适合当前情况的出行方式。

**结构:**策略模式通常由以下几个部分组成:

  1. 策略接口(Strategy Interface):定义了一个通用接口,所有具体策略类都实现这个接口。
  2. 具体策略类(Concrete Strategy Class):实现策略接口,提供具体的算法。
  3. 上下文类(Context Class):持有一个策略接口的引用,负责动态地选择和执行某个具体策略。上下文类在策略模式中扮演着一个重要角色,它不仅负责持有策略对象,还可能包含一些与策略相关的状态信息或辅助方法,以便于策略的执行。

优点:

  • 灵活性:可以根据需要在运行时动态地改变对象的算法或行为。
  • 扩展性:增加新的策略时,只需添加新的策略类即可,无需修改已有代码。
  • 简化代码:将算法的实现和使用分离,使代码更加简洁和易于维护。

2. 代码演示

场景:模拟出行方式,有开车、坐火车、或者乘飞机三种出行策略。

2.1 常规用法

策略接口(Strategy Interface):

java 复制代码
public interface TravelStrategy {
    void travel();
}

具体策略类(Concrete Strategy Class):

java 复制代码
// 具体策略类 - 开车
public class CarTravelStrategy implements TravelStrategy {
    @Override
    public void travel() {
        System.out.println("Traveling by car.");
    }
}

// 具体策略类 - 火车
public class TrainTravelStrategy implements TravelStrategy {
    @Override
    public void travel() {
        System.out.println("Traveling by train.");
    }
}

// 具体策略类 - 飞机
public class PlaneTravelStrategy implements TravelStrategy {
    @Override
    public void travel() {
        System.out.println("Traveling by plane.");
    }
}

上下文类(Context Class):

java 复制代码
public class TravelContext {
    private TravelStrategy strategy;
    //一些与策略相关的信息
    private String travelTime;

    public TravelContext(String travelTime) {
        this.travelTime = travelTime;
    }

    public void setStrategy(TravelStrategy strategy) {
        this.strategy = strategy;
    }

    public void executeTravel() {
        System.out.println("Travel time: " + travelTime);
        strategy.travel();
    }
}

**客户端代码:**使用策略模式

java 复制代码
public class StrategyPatternDemo {
    public static void main(String[] args) {
        TravelContext context = new TravelContext("Morning");

        // 使用开车策略
        context.setStrategy(new CarTravelStrategy());
        context.executeTravel();

        // 使用火车策略
        context.setStrategy(new TrainTravelStrategy());
        context.executeTravel();

        // 使用飞机策略
        context.setStrategy(new PlaneTravelStrategy());
        context.executeTravel();
    }
}

对应的类图:

2.2 使用策略工厂优化

上述常规用法中,策略对象的创建比较简单,客户端在使用策略时顺手创建了对象。如果策略创建逻辑比较复杂,这种用法会增加客户端的复杂度,此时可以使用策略工厂优化。

策略工厂并不是策略模式的必需部分,但它可以在某些场景下增加策略模式的灵活性和可维护性。策略工厂的主要作用是负责创建策略对象,这样可以将策略的选择逻辑封装起来,使得客户端代码更简洁,并且可以更容易地管理和扩展策略。

引入策略工厂后,只需修改上下文类和客户端代码,其他保持不变。

新增策略工厂(StrategyFactory):

java 复制代码
public class TravelStrategyFactory {
    public static TravelStrategy getStrategy(String preference) {
        switch (preference.toLowerCase()) {
            case "car":
                return new CarTravelStrategy();
            case "train":
                return new TrainTravelStrategy();
            case "plane":
                return new PlaneTravelStrategy();
            default:
                throw new IllegalArgumentException("Unknown travel preference: " + preference);
        }
    }
}

上下文类(Context Class)修改如下:

java 复制代码
public class TravelContext {
    private TravelStrategy strategy;
    private String travelTime;

    public TravelContext(String travelTime) {
        this.travelTime = travelTime;
    }
    
    //根据用户选择的交通工具名称,使用策略工厂获取对应策略
    public void setStrategy(String preference) {
        this.strategy = TravelStrategyFactory.getStrategy(preference);
    }

    public void executeTravel() {
        System.out.println("Travel time: " + travelTime);
        strategy.travel();
    }
}

客户端代码修改如下:

java 复制代码
public class StrategyPatternDemo {
    public static void main(String[] args) {
        TravelContext context = new TravelContext("Morning");

        // 使用开车策略; 直接传入交通工具名称即可
        context.setStrategy("car");
        context.executeTravel();

        // 使用火车策略
        context.setStrategy("train");
        context.executeTravel();

        // 使用飞机策略
        context.setStrategy("plane");
        context.executeTravel();
    }
}

对应的类图:

引入策略工厂的优点:

  1. 封装选择逻辑:策略工厂将策略选择的逻辑集中在一个地方,使得上下文或客户端代码更简洁。
  2. 易于扩展:当需要添加新的策略时,只需更新工厂的创建逻辑,而不需要修改上下文或客户端代码。
  3. 减少耦合:上下文或客户端代码与具体策略的创建解耦,使得代码更易于维护。

虽然策略工厂不是策略模式的核心部分,但在一些复杂的场景中,它可以显著提高代码的组织性和可维护性。根据项目需求和复杂度,可以选择是否使用策略工厂。

相关推荐
晚安code3 小时前
干掉成山的 if-else:工厂造、策略选,一文讲透两个模式的配合
后端·设计模式
摇滚侠4 小时前
《RocketMQ 官网》阅读笔记 RocketMQ 消息队列 MessageQueue 消息 Messagege
笔记·rocketmq
Ztt6666666665 小时前
【无标题】
经验分享·笔记·其他·百度·微信公众平台
依然范特东5 小时前
强化学习笔记4--TD算法
笔记
AOwhisky6 小时前
Linux(CentOS)系统管理入门笔记(第十五期)——文件系统与存储管理(上篇):设备识别、挂载与文件查找
linux·运维·笔记·centos·文件系统
茯苓gao7 小时前
嵌入式开发笔记:QSerialPort 完整使用指南——从基础 API 到工程实战
笔记·嵌入式硬件·qt·学习
一起努力啊~7 小时前
DataWhale组队学习笔记--llm-algo-leetcode(七)
笔记·学习·llm
ajassi20008 小时前
AI语音智能体开发日记(一)如何为“小智”服务器启用并调试 License 功能
笔记·ai·嵌入式·ai编程
疯狂打码的少年9 小时前
【面向对象】面向对象概述:从“按步骤做”到“找谁来做”
笔记
今夜有雨.9 小时前
C++JSON 解析器
c++·笔记·后端·学习·json