【Java设计模式】行为型设计模式-策略模式(十三)

策略模式

  • 策略模式将各种不同类型所对应的不同执行逻辑抽象成算法族(策略组),并分别封装起来,让他们之间可以互相替换,这样就将算法的变化和使用算法的客户端分离开来。
  • 这样体现了几个设计原则:
    • 把变化的代码从不变的代码中分离出来。
    • 针对接口编程而不是具体类(定义了策略接口)。
    • 多用组合/聚合,少用继承(客户通过组合方式使用策略)。

进一步阐述:策略模式就是解决具体逻辑和客户端耦合在一起的问题,其核心是找到项目中变化的部分并进行抽离出来成为一个接口,项目中不变的部分就直接使用接口调用抽象方法即可。

策略模式包含三种角色:

  • Context(环境角色):用来操作策略的上下文环境,它持有一个Strategy的引用。
  • Strategy(抽象策略角色):所有策略的抽象,封装了需要去执行的项目中不变的部分逻辑。
  • ConcreteStrategy (具体策略角色):抽象策略的实现,每一种不同的逻辑执行方式就是一个具体的策略类。

案例:我们以一个旅行者为例,旅行的方式有很多种,可以坐高铁,也可以坐飞机,这取决于用户自己的选择。其中旅行者Traveler类就是环境角色,旅行策略TravelingStrategy接口就是抽象策略角色,飞机旅行策略AirTravelingStrategy实现类和高铁旅行策略HightTrainTravelingStrategy实现类就是具体的策略角色。

UML类图:

客户端Client类:

java 复制代码
/**
 * 客户端
 */
public class Client {
​
    public static void main(String[] args) {
​
        Traveler traveler = new Traveler(new HightTrainTravelingStrategy());
​
        traveler.goTraveling();
    }
}

旅行者Traveler类:

java 复制代码
/**
 * 旅行者类
 */
public class Traveler {
​
    //持有一个旅行策略接口的实现类
    private TravelingStrategy travelingStrategy;
​
    public Traveler(TravelingStrategy travelingStrategy) {
        this.travelingStrategy = travelingStrategy;
    }
​
    public void goTraveling() {
        //省去了繁琐的if-- else if -- else if
        travelingStrategy.goTraveling();
    }
}

旅行策略TravelingStrategy接口:

java 复制代码
/**
 * 旅行策略接口
 */
public interface TravelingStrategy {
​
    /**
     * 去旅游方法
     */
    void goTraveling();
}

高铁旅行策略HightTrainTravelingStrategy实现类:

java 复制代码
/**
 * 高铁旅行策略实现类
 */
public class HightTrainTravelingStrategy implements TravelingStrategy {
​
    @Override
    public void goTraveling() {
        System.out.println("乘坐高铁去旅行......");
    }
}

飞机旅行策略AirTravelingStrategy实现类:

java 复制代码
/**
 * 飞机旅行策略实现类
 */
public class AirTravelingStrategy implements TravelingStrategy {
​
    @Override
    public void goTraveling() {
        System.out.println("乘坐飞机去旅行......");
    }
}

总结:

  • 客户端增加行为不用修改原有代码,只要添加一种策略(或者行为)即可,避免了使用if--else if--else if去完成逻辑的编程的情况,是典型的if--else if--else if的"杀手",因为遵守了开闭原则(OCP原则),所以极大地提高了软件的可扩展性、可维护性。
  • 策略模式的核心思想是:多用组合或者聚合少用继承;用行为类进行组合,而不是行为类进行继承,这样耦合度降低了,这样就替换了用继承关系解决问题的办法,策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改变它,使它易于切换、易于理解、易于扩展遵守了合成复用原则。
  • 使用策略模式的客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
  • 策略模式如果策略有很多那么就会出现很多的策略类增加了系统类的复杂度。
  • Context在使用这些策略类的时候,这些策略类由于实现了策略接口,所以有些数据可能用不到,但是依然初始化了,这样就造成了内存的浪费。

典型运用场景举例: 电商项目的优惠活动管理,优惠的策略有很多种,包括满减类型优惠策略、打折类优惠策略、赠送礼品策略、发放优惠券策略。

相关推荐
李昊哲小课几秒前
Spring Boot 4 旅游主题实战教程 阶段三:数据持久化
spring boot·后端·mybatis·旅游
JienDa4 分钟前
我做了一款不依赖 AI 的离线传统术数排盘工具:Electron、Vue3 与 Java 17 的完整实践
java·人工智能·electron
AI 编程助手GPT5 分钟前
Bun 1.4 正式发布:从 Zig 改写为 Rust,内置浏览器、图片处理和并行测试
开发语言·人工智能·后端·ai·chatgpt
非凡ghost14 分钟前
用 Kotlin 和 Jetpack Compose 重写的安卓视频播放器,原生体验有多流畅?
android·java·kotlin·音视频·软件需求
ttwosix20 分钟前
JavaEE初阶 多线程 3
java·开发语言
asdfg125896323 分钟前
一个例子通俗理解Java中正则表达式用法
java·正则表达式
一嘴一个橘子27 分钟前
MyBatis‑Plus Service 层常用自带方法
java
健康平安的活着30 分钟前
java中批量查询+stream返回map提高查询效率
java·windows·python
wear工程师31 分钟前
Spring 循环依赖为什么要三级缓存:两级会把 AOP 代理弄丢
java·spring
IT_陈寒31 分钟前
Redis大KEY删除慢到手抖,这几个方法让我少熬一夜
前端·人工智能·后端