带你走进不一样的策略模式

news2024/11/20 18:45:22

欢迎来到我的博客,代码的世界里,每一行都是一个故事


在这里插入图片描述

带你走进不一样的策略模式

    • 前言
    • 策略模式简介
      • 概念解释
    • 策略模式的结构
    • 策略模式优点
    • 项目实践之bean策略
      • 构思业务
      • 策略实现
        • 策略接口实现
        • 策略上下文
        • 业务实现

前言

在编程的世界里,每一次按键都是在与代码做策略游戏。我们试图在效率、灵活性和可维护性之间找到平衡点。今天,我们要探讨的是Java中的策略模式,这个模式就像是一个老练的军师,让我们在面对不断变化的需求时能够灵活调整战略。在本文中,我们不仅要学习策略模式的理论,更要通过实战将这个强大的工具纳入我们的编程武库。准备好了吗?让我们开始这场精彩的策略之旅吧

策略模式简介

策略模式(Strategy Pattern)是一种设计模式,它使得一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

概念解释

策略(Strategy):一个策略代表了一个算法,或者说是一个行为。在策略模式中,我们可以定义一系列算法或行为,并将每一个算法封装到具有共同接口的独立的类中。
上下文(Context):上下文是使用策略的对象。通常,它会持有一个指向策略对象的引用,并可通过该引用调用策略对象实现的算法。上下文可能会定义一个接口来让策略对象访问它的数据。
策略接口(Strategy Interface):这是一个定义每个策略或算法必须遵守的接口。它是一个共同的接口,让上下文能够在不同策略之间切换而不影响客户端。
具体策略(Concrete Strategies):实现策略接口的类,提供具体的算法或行为。

策略模式的结构

Strategy(策略接口):定义所有支持的算法的公共接口。Context 使用这个接口来调用 ConcreteStrategy 定义的算法。
ConcreteStrategy(具体策略):实现 Strategy 接口的具体类。每一个 ConcreteStrategy 提供了一个算法或行为。
Context(上下文):持有一个对 Strategy 对象的引用。它可以定义一个接口来让 Strategy 访问它的数据。

// 策略接口
public interface Strategy {
    public void execute();
}
// 具体策略A
public class ConcreteStrategyA implements Strategy {
    public void execute() {
        System.out.println("执行策略A");
    }
}
// 具体策略B
public class ConcreteStrategyB implements Strategy {
    public void execute() {
        System.out.println("执行策略B");
    }
}
// 上下文
public class Context {
    private Strategy strategy;

    // 构造方法,传入策略对象
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
    
    // 上下文接口
    public void executeStrategy() {
        strategy.execute();
    }
}
// 客户端代码
public class StrategyPatternDemo {
    public static void main(String[] args) {
        Context context = new Context(new ConcreteStrategyA()); // 使用策略A
        context.executeStrategy(); // 输出:执行策略A

        context = new Context(new ConcreteStrategyB()); // 使用策略B
        context.executeStrategy(); // 输出:执行策略B
    }
}

策略模式优点

策略模式是一种常用的设计模式,它提供了一系列显著的优点,特别是在处理算法、行为或策略需要在运行时可更换的场景中。以下是策略模式的一些主要优点:

  1. 代码复用与分离
    策略模式通过将算法封装在独立的策略类中,实现了算法的复用。这种封装也促进了算法逻辑和使用算法的客户端代码之间的分离。每个策略类负责自己的算法,使得算法的管理和维护变得更加清晰和简单。
  2. 易于扩展
    策略模式使得添加新的策略或算法变得非常容易,而不需要修改现有的代码。这是因为策略模式提供了一个共同的接口给所有的策略类,任何新的策略实现都可以通过实现这个接口加入到系统中,而不会影响到使用策略的客户端代码。这种易于扩展的特性使得系统更加灵活,能够更好地适应变化。
  3. 替换继承
    在一些情况下,使用策略模式可以避免使用继承来提供类的不同行为。在传统的面向对象设计中,继承被广泛用于扩展类的功能。然而,继承有其固有的缺点,如可能导致类层次结构变得复杂,以及子类与父类之间的紧密耦合。策略模式提供了一种替代继承的方法,通过组合的方式(即在类中引入策略对象)来改变类的行为,这样做可以提高类的灵活性和可维护性。
  4. 更好的测试性
    由于策略模式将算法的实现从其使用环境中分离出来,测试各个算法变得更加容易。每个策略类可以独立于上下文进行单元测试,这有助于识别和修复潜在的算法错误,提高代码的质量。
  5. 更好的控制算法族
    在策略模式中,所有相关的算法族都被封装在一个定义良好的策略接口后面。这不仅使得算法的管理变得容易,而且还可以在运行时动态地在不同算法之间进行切换,为客户端代码提供了更大的灵活性和控制力。
    综上所述,策略模式通过提供一种机制来分离和封装算法或行为,使得代码更加模块化、易于扩展和维护,同时也提高了代码的复用性和灵活性。这些优点使得策略模式在众多设计模式中占有一席之地。

项目实践之bean策略

构思业务

现在我有一个业务它需要根据某一个判断条件(类型)来选择调用某一bean中的相关方法,传统的实现方式如下图

202404210951557.png

对于上面的方式,会存在这样一个问题,每当我新加一个类型,就要新加一个service实现。并且我的业务中要新加判断,如果我这个业务中存在一个方法会新加一个,如果是100个可能就会新加100个。这样不仅违法了开闭原则,而且还有冗余代码且改起来费时间,最终演变为策略模式,如下图

202404211007531.png

策略实现

策略接口实现
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * @author xiaobo
 */
public interface IDataStrategy {

    /**
     * description: 判断是否有值
     *
     * @param mainType 主要类型
     * @return boolean
     * @date 2024/4/19 15:57
     */
    boolean supports(String mainType);

}
策略上下文
package com.jxth.dasmart.bridge.configs;

import com.jxth.dasmart.bridge.modules.mid.IMidDataStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * description: 策略管理
 *
 * @author bo
 * @version 1.0
 * @date 2024/4/19 16:10
 */
@Component
@RequiredArgsConstructor
public class DataServiceManager {
    private final List<IMidDataStrategy> services;

    public IMidDataStrategy getService(String mainType) {
        return services.stream()
                .filter(service -> service.supports(mainType))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("No suitable service found for mainType: " + mainType));
    }
}
业务实现
public class BusinessTest {
  @Resource
  protected DataServiceManager serviceManager;

  public void test(String type){
    IDataStrategy service = serviceManager.getService(type);
    // 实现相关方法
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1624085.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Golang对接Ldap(保姆级教程:概念搭建实战)

Golang对接Ldap&#xff08;保姆级教程&#xff1a;概念&搭建&实战&#xff09; 最近项目需要对接客户的LDAP服务&#xff0c;于是趁机好好了解了一下。LDAP实际是一个协议&#xff0c;对应的实现&#xff0c;大家可以理解为一个轻量级数据库。用户查询。比如&#xff…

高频前端面试题汇总之Vue篇

1. Vue的基本原理 当一个Vue实例创建时&#xff0c;Vue会遍历data中的属性&#xff0c;用 Object.defineProperty&#xff08;vue3.0使用proxy &#xff09;将它们转为 getter/setter&#xff0c;并且在内部追踪相关依赖&#xff0c;在属性被访问和修改时通知变化。 每个组件实…

【ruoyi-vue】登录解析(后端)

调试登录接口 进入实现类可以有 验证码校验 登录前置校验 用户验证 验证码校验 通过uuid获取redis 中存储的验证码信息&#xff0c;获取后对用户填写的验证码数据进行校验比对 用户验证 1.进入控制器的 /login 方法 2.进入security账号鉴权功能&#xff0c;经过jar内的流…

算法-动态规划专题

文章目录 前言 : 动态规划简述1 . 斐波那契模型1.1 泰波那契数列1.2 最小花费爬楼梯1.3 解码方法 前言 : 动态规划简述 动态规划在当前我们的理解下,其实就是一种变相的递归,我们查看一些资料也可以知道,动态规划其实属于递归的一个分支,通过把递归问题开辟的栈帧通过一定的手…

代码随想录第45天|70. 爬楼梯 (进阶)322. 零钱兑换

70. 爬楼梯 &#xff08;进阶&#xff09; 57. 爬楼梯&#xff08;第八期模拟笔试&#xff09; (kamacoder.com) 代码随想录 (programmercarl.com) 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬至多m (1 < m < n)个台阶。你有多少种不同的方法可以爬到楼顶…

企业数字化转型,“业务”先行

在当今时代&#xff0c;数字化转型已经成为企业发展的必经之路。数字化转型&#xff0c;简而言之&#xff0c;就是运用数字技术&#xff0c;对企业运营管理的各个环节进行深度改造&#xff0c;以提升企业的运营效率和市场竞争力。据有关机构研究测算&#xff0c;数字化转型可使…

【静态分析】静态分析笔记07 - 指针分析基础

参考&#xff1a; 【课程笔记】南大软件分析课程7——指针分析基础&#xff08;课时9/10&#xff09; - 简书 -------------------------------------------------------------- 1. 指针分析规则 规则&#xff1a;采用推导形式&#xff0c;横线上面是条件&#xff0c;横线下…

Linux开发板配置静态IP

1、查看网口信息&#xff0c;易知eth0无IP地址 ifconfig2、首先分配一个IP地址 sudo ifconfig eth0 192.168.5.8 up3、此时配置的IP地址只是临时的&#xff0c;当你reboot重启板子上电后&#xff0c;ip地址会消失&#xff0c;因此需要为板子配置静态ip&#xff0c;避免每次上…

说方法不如传授经验向媒体投稿你可以这样

在信息爆炸的时代,作为单位的信息宣传员,肩负着将本单位的重要资讯、活动成果、政策解读等内容有效传播至公众视野的重任。其中,向各类媒体投稿无疑是实现这一目标的重要途径。然而,传统的邮件投稿方式常常让我深感力不从心,费时费力不说,成功率低、出稿慢等问题更是让我和领导…

SQL注入简单总结

一、SQL注入是什么 SQL注入即&#xff1a;是指web应用程序对用户输入数据的合法性没有判断或过滤不严&#xff0c;攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句&#xff0c;在管理员不知情的情况下实现非法操作&#xff0c;以此来实现欺骗数据库服…

【论文推导】基于有功阻尼的转速环PI参数整定分析

前言 在学习电机控制的路上&#xff0c;PMSM的PI电流控制是不可避免的算法之一&#xff0c;其核心在于内环电流环、外环转速环的设置&#xff0c;来保证转速可调且稳定&#xff0c;并且保证较好的动态性能。整个算法仿真在《现代永磁同步电机控制原理及matlab仿真》中已详细给出…

前端项目中使用插件prettier/jscodeshift/json-stringify-pretty-compact格式化代码或json数据

同学们可以私信我加入学习群&#xff01; 正文开始 前言一、json代码格式化-选型二、json-stringify-pretty-compact简单试用三、prettier在前端使用四、查看prettier支持的语言和插件五、使用prettier格式化vue代码最终效果如图&#xff1a; ![在这里插入图片描述](https://im…

3.8设计模式——State 状态模式(行为型)

意图 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 结构 Context&#xff08;上下文&#xff09;定义客户感兴趣的接口&#xff1b;维护一个ConcreteState子类的实例&#xff0c;这个实例定义当前状态。State&#xff08;状态&#xff09;定义…

[x86] OpenBMC简介

什么是 OpenBMC&#xff1f; OpenBMC 被设计为一个完整的开源 Linux 发行版&#xff0c;可以灵活地进行定制以支持不同的 SoC 或主板。 传统的BMC由固件提供商专有构建&#xff0c;是闭源的&#xff0c;这意味着它不具有在开放平台上修改的灵活性。 另一方面&#xff0c;OpenB…

链栈的基本操作(c语言实现)

栈的概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 栈的结构 定义栈…

做抖音小店,“自然流量”和“达人带货”,选择哪个更香?

大家好&#xff0c;我是电商笨笨熊 做抖音小店&#xff0c;关于选择自然流还是达人带货&#xff0c;从推出时就一直争吵到现在&#xff1b; 有人觉得自然流不需要佣金&#xff0c;一次性带来的爆单量很大&#xff1b; 有人觉得达人带货细水长流&#xff0c;虽然需要佣金&…

Docker 网络与资源控制

一 Docker 网络实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c;Docker启动一个容器时会根 据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为Container-IP&#xff0c;同时Docker网桥是每个容器的默 认网关。因为在同…

2000-2022年各区县农产品产量数据

2000-2022年县域农产品产量数据 1、时间&#xff1a;2000-2022年 2、指标&#xff1a;统计年度、县域名称、所属地级市、所属省份、地区编码ID、县域代码、产品种类或名称、单位、产量、 3、来源&#xff1a;统计局、县域统计年鉴、各区县政府官网 4、范围&#xff1a;具体…

基于Linux的Ncurse库的贪吃蛇项目

贪吃蛇项目的意义 承上启下&#xff1a;从C语言基础的学习&#xff1a;数据结构链表基础、C变量、流程控制、函数、指针、结构体等。过渡到Linux系统编程&#xff1a;文件编程、进程、线程、通信、第三方等。 Linux终端图形库curses curses的名字起源于"cursor optimiz…

算法学习笔记Day8——回溯算法

本文解决几个问题&#xff1a; 回溯算法是什么&#xff1f;解决回溯算法相关的问题有什么技巧&#xff1f;回溯算法代码是否有规律可循&#xff1f; 一、介绍 1.回溯算法是什么&#xff1f; 回溯算法就是个多叉树的遍历问题&#xff0c;关键在于在前序和后序时间点做一些操作…