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

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. 减少耦合:上下文或客户端代码与具体策略的创建解耦,使得代码更易于维护。

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

相关推荐
lingggggaaaa1 小时前
小迪安全v2023学习笔记(六十一讲)—— 持续更新中
笔记·学习·安全·web安全·网络安全·反序列化
不太可爱的叶某人2 小时前
【学习笔记】Java并发编程的艺术——第6章 Java并发容器和框架
java·笔记·学习
超勇的阿杰3 小时前
gulimall项目笔记:P54三级分类拖拽功能实现
android·笔记
易元4 小时前
模式组合应用-桥接模式(一)
后端·设计模式
是2的10次方啊4 小时前
🕺 行为型设计模式:对象协作的舞蹈家(中)
设计模式
the sun344 小时前
常见的设计模式(2)单例模式
单例模式·设计模式
₯㎕星空&繁华5 小时前
Linux-地址空间
linux·运维·服务器·经验分享·笔记
是2的10次方啊5 小时前
🕺 行为型设计模式:对象协作的舞蹈家(上)
设计模式
诗书画唱5 小时前
学习笔记与效率提升指南:编程、记忆与面试备考
笔记·学习·面试