案例突破——再探策略模式
再探设计模式
- 一、背景介绍
- 二、 思路方案
- 三、过程
- 1. 策略模式基本概念
- 2. 策略模式类图
- 3. 策略模式基本代码
- 策略类
- 抽象策略类
- Context类
- 客户端
- 4. 策略模式还可以进行优化的地方
- 5. 对策略模式的优化(配置文件+反射)
- 四、总结
- 五、升华
一、背景介绍
在做项目重构的过程中,发现对于主题讨论中,针对于学生评论/回复的内容的按照评论/回复日期排序、按照评论数量排序、按照点赞次数排序可以使用策略模式进行优化。
二、 思路方案
- 策略模式基本概念
- 策略模式类图
- 策略模式基本代码
- 策略模式还可以进行优化的地方
- 对策略模式进行优化
三、过程
1. 策略模式基本概念
定义:定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化不会影响到使用算法的客户。
2. 策略模式类图

3. 策略模式基本代码
策略类
package com.wangwei.strategypattern.normal;/*** @author : [WangWei]* @version : [v1.0]* @className : ConcreteStrategy* @description : [描述说明该类的功能]* @createTime : [2023/9/7 10:34]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:34]* @updateRemark : [描述说明本次修改内容]*/
public class ConcreteStrategyA implements IStrategy{public void AlgorithmInterface(){System.out.println("算法A实现");}
}package com.wangwei.strategypattern.normal;/*** @author : [WangWei]* @version : [v1.0]* @className : ConcreteStrategy* @description : [描述说明该类的功能]* @createTime : [2023/9/7 10:34]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:34]* @updateRemark : [描述说明本次修改内容]*/
public class ConcreteStrategyB implements IStrategy{public void AlgorithmInterface(){System.out.println("算法B实现");}
}package com.wangwei.strategypattern.normal;/*** @author : [WangWei]* @version : [v1.0]* @className : ConcreteStrategy* @description : [描述说明该类的功能]* @createTime : [2023/9/7 10:34]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:34]* @updateRemark : [描述说明本次修改内容]*/
public class ConcreteStrategyC implements IStrategy{public void AlgorithmInterface(){System.out.println("算法C实现");}
}
抽象策略类
package com.wangwei.strategypattern.normal;/*** @author : [WangWei]* @version : [v1.0]* @className : IStrategy* @description : [描述说明该类的功能]* @createTime : [2023/9/7 10:37]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:37]* @updateRemark : [描述说明本次修改内容]*/
public interface IStrategy {void AlgorithmInterface();
}
Context类
package com.wangwei.strategypattern.normal;/*** @author : [WangWei]* @version : [v1.0]* @className : Context* @description : [公共上下文]* @createTime : [2023/9/7 10:38]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:38]* @updateRemark : [描述说明本次修改内容]*/
public class Context {IStrategy iStrategy=null;public Context(IStrategy iStrategy) {this.iStrategy = iStrategy;}public void ContextInterface(){iStrategy.AlgorithmInterface();}
}
客户端
package com.wangwei.strategypattern.normal;/*** @author : [WangWei]* @version : [v1.0]* @className : Client* @description : [描述说明该类的功能]* @createTime : [2023/9/7 10:40]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:40]* @updateRemark : [描述说明本次修改内容]*/
public class Client {public static void main(String[] args) {Context context=null;context= new Context(new ConcreteStrategyA());context.ContextInterface();context = new Context(new ConcreteStrategyB());context.ContextInterface();context = new Context(new ConcreteStrategyB());context.ContextInterface();}
}
4. 策略模式还可以进行优化的地方
当我们需要增加新的策略的时候,是需要修改客户端的代码,那么对于客户端来说是不符合开闭原则的。
5. 对策略模式的优化(配置文件+反射)
package com.wangwei.strategypattern.better;/*** @author : [WangWei]* @version : [v1.0]* @className : ConcreteStrategy* @description : [描述说明该类的功能]* @createTime : [2023/9/7 10:34]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:34]* @updateRemark : [描述说明本次修改内容]*/
public class ConcreteStrategyA implements IStrategy {public void AlgorithmInterface(){System.out.println("算法A实现");}
}
package com.wangwei.strategypattern.better;/*** @author : [WangWei]* @version : [v1.0]* @className : ConcreteStrategy* @description : [描述说明该类的功能]* @createTime : [2023/9/7 10:34]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:34]* @updateRemark : [描述说明本次修改内容]*/
public class ConcreteStrategyB implements IStrategy {public void AlgorithmInterface(){System.out.println("算法B实现");}
}
package com.wangwei.strategypattern.better;/*** @author : [WangWei]* @version : [v1.0]* @className : ConcreteStrategy* @description : [描述说明该类的功能]* @createTime : [2023/9/7 10:34]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:34]* @updateRemark : [描述说明本次修改内容]*/
public class ConcreteStrategyC implements IStrategy {public void AlgorithmInterface(){System.out.println("算法C实现");}
}
package com.wangwei.strategypattern.better;import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;/*** @author : [WangWei]* @version : [v1.0]* @className : Context* @description : [公共上下文]* @createTime : [2023/9/7 10:38]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:38]* @updateRemark : [描述说明本次修改内容]*/
public class Context {static Map<String,String> config = new HashMap<>();static Map<String,IStrategy> configBean = new HashMap<>();//提前读取配置文件中的策略,并提前准备好已有的策略对象static {InputStream inputStream = Context.class.getResourceAsStream("/config.properties");Properties properties = new Properties();try {properties.load(inputStream);} catch (IOException e) {throw new RuntimeException(e);}String strategyType = properties.getProperty("strategyType");String[] strs = strategyType.split(",");for (String string : strs) {String key = string.split(":")[0];String value = string.split(":")[1];// 去掉头部空格String key1 = key.trim();String value1 = value.trim();config.put(key1, value1);}//提前准备好已有的策略对象for (Map.Entry<String,String> entry:config.entrySet()) {Class strategyClass ;try {strategyClass = Class.forName(entry.getValue());configBean.put(entry.getKey(),(IStrategy) strategyClass.getConstructor().newInstance());} catch (Exception e) {throw new RuntimeException(e);}}}IStrategy iStrategy;public Context(String type) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException {if(configBean.containsKey(type)){this.iStrategy = configBean.get(type);}else {Class strategyClass = Class.forName(config.get(type));this.iStrategy = (IStrategy)strategyClass.getConstructor().newInstance();}}public void ContextInterface(){iStrategy.AlgorithmInterface();}}
package com.wangwei.strategypattern.better;/*** @author : [WangWei]* @version : [v1.0]* @className : IStrategy* @description : [描述说明该类的功能]* @createTime : [2023/9/7 10:37]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:37]* @updateRemark : [描述说明本次修改内容]*/
public interface IStrategy {void AlgorithmInterface();
}
package com.wangwei.strategypattern.better;import java.io.IOException;
import java.lang.reflect.InvocationTargetException;/*** @author : [WangWei]* @version : [v1.0]* @className : Client* @description : [描述说明该类的功能]* @createTime : [2023/9/7 10:40]* @updateUser : [WangWei]* @updateTime : [2023/9/7 10:40]* @updateRemark : [描述说明本次修改内容]*/
public class Client {public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException {/*1.前端通过下拉框选择不同的类型2.类型是从配置文件中读取的*/Context context;context= new Context("strategyA");context.ContextInterface();context = new Context("strategyB");context.ContextInterface();context = new Context("strategyC");context.ContextInterface();}
}
四、总结
-
优点:配置文件+反射的方式,符合开闭原则。用户可以在不修改原有代码的基础上选择算法,也可以灵活的增加新的算法。
-
缺点:无法同时在客户端使用多个策略类。
-
关键点:都是对通一份数据,根据不同的算法进行处理。
-
什么时候使用策略模式:一个系统需要动态地在几种算法中选择一种。
五、升华
- 学习是一个反复的过程:通过项目切实的需求来结合具体的设计模式,在反过来在此基础上优化设计模式。
相关文章:
案例突破——再探策略模式
再探设计模式 一、背景介绍二、 思路方案三、过程1. 策略模式基本概念2. 策略模式类图3. 策略模式基本代码策略类抽象策略类Context类客户端 4. 策略模式还可以进行优化的地方5. 对策略模式的优化(配置文件反射) 四、总结五、升华 一、背景介绍 在做项目…...
uboot启动流程-涉及lowlevel_init汇编函数
一. uboot启动流程涉及函数 之前文章简单分析了 uboot启动流程的开始,从链接脚本文件 u-boot.lds 中,我们已经知道了入口点是 arch/arm/lib/vectors.S 文件中的 _start函数。 _start函数:调用了 reset 函数,reset 函数内部&…...
质数距离 - 如何在较合理的时间复杂度内求2e9范围内的质数
求l、r之间的质数,范围在2e9,但l、r的差值不大,在1e6范围内 先求出 内的质数,然后拿这个指数去筛[l, r]范围内的即可 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \…...
八、3d场景的区域光墙
在遇到区域展示的时候我们就能看到炫酷的区域选中效果,那么代码是怎么编辑的呢,今天咱们就好好说说,下面看实现效果。 思路: 首先,光墙肯定有多个,那么必须要创建一个新的js文件来作为他的原型对象。这个光…...
深入探讨 Presto 中的缓存
【squids.cn】 全网zui低价RDS,免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 Presto是一种流行的开源分布式SQL引擎,使组织能够在多个数据源上大规模运行交互式分析查询。缓存是一种典型的提高 Presto 查询性能的优化技术。它为 Prest…...
3.物联网射频识别,(高频)RFID应用ISO14443-2协议,(校园卡)Mifare S50卡
一。ISO14443-2协议简介 1.ISO14443协议组成及部分缩略语 (1)14443协议组成(下面的协议简介会详细介绍) 14443-1 物理特性 14443-2 射频功率和信号接口 14443-3 初始化和防冲突 (分为Type A、Type B两种接口&…...
【IDEA】IDEA 单行注释开头添加空格
操作 打开 IDEA 的 Settings 对话框(快捷键为CtrlAltS);在左侧面板中选择Editor -> Code Style -> Java;在右侧面板中选择Code Generation选项卡;将Line comment at first column选项设置为false使注释加在行开…...
三等分功分器[波导]设计详细教程
想必大家通过阅读相关文献可以发现三等分实现可以有很多不同的方法,这里采用的是先不等分再等分的方式,仅供参考。 主要指标 中心频率为280GHz,采用WR-3频段的标准波导,将2:1不等功率分配耦合器与3dB等功率分配耦合器级联&#…...
Mysql分库分表
1.原理 2.Sharding JDBC 官网https://shardingsphere.apache.org/ 2.1 水平拆分 创建一个新的springboot项目 导入依赖,直接将原本的dependencies给覆盖掉 <dependencies><!-- ShardingJDBC依赖 --><dependency><groupId>org.apache.shardings…...
【算法学习】-【双指针】-【复写零】
LeetCode原题链接:1089. 复写零 下面是题目描述: 给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。 注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 …...
【算法优选】双指针专题——叁
文章目录 😎前言🌳[两数之和](https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/)🚩题目描述:🚩算法思路:🚩算法流程:🚩代码实现 🎄[三数之和]…...
Java栈的压入、弹出序列(详解)
目录 1.题目描述 2.题解 方法1 方法2 1.题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序…...
RabbitMQ学习笔记(消息发布确认,死信队列,集群,交换机,持久化,生产者、消费者)
MQ(message queue):本质上是个队列,遵循FIFO原则,队列中存放的是message,是一种跨进程的通信机制,用于上下游传递消息。MQ提供“逻辑解耦物理解耦”的消息通信服务。使用了MQ之后消息发送上游只…...
PyTorch - 模型训练损失 (Loss) NaN 问题的解决方案
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/133378367 在模型训练中,如果出现 NaN 的问题,严重影响 Loss 的反传过程,因此,需要加入一些微小值…...
8、Nacos服务注册服务端源码分析(七)
本文收录于专栏 Nacos 中 。 文章目录 前言确定前端路由CatalogController.listDetail()ServiceManager总结 前言 前文我们分析了Nacos中客户端注册时数据分发的设计链路,本文根据Nacos前端页面请求,看下前端页面中的服务列表的数据源于哪里。 确定前端…...
MySQL使用Xtrabackup在线做主从
1、主库上操作 1.1前提 172.16.11.2(主库) 172.16.11.4(从库) 在执行备份之前,确保数据库没有锁定,以避免备份期间的任何写操作。 确保主库上的 MySQL 服务器正在运行,以便备份数据的一致性。…...
scala基础入门
一、Scala安装 下载网址:Install | The Scala Programming Language ideal安装 (1)下载安装Scala plugins (2)统一JDK环境,统一为8 (3)加载Scala (4)创建工…...
【Java-LangChain:面向开发者的提示工程-5】推断
第五章 推断 推断任务可以看作是模型接收文本作为输入,并执行某种分析的过程。其中涉及提取标签、提取实体、理解文本情感等等。如果你想要从一段文本中提取正面或负面情感,在传统的机器学习工作流程中,需要收集标签数据集、训练模型、确定如…...
【C++】手撕vector(vector的模拟实现)
手撕vector目录: 一、基本实现思路方针 二、vector的构造函数剖析(构造歧义拷贝构造) 2.1构造函数使用的歧义问题 2.2 vector的拷贝构造和赋值重载(赋值重载不是构造哦,为了方便写在一起) 三、vector的…...
智能指针那些事
《Effective Modern C》学习笔记之条款二十一:优先选用std::make_unique和std::make_shared,而非直接new - 知乎...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
机器学习的数学基础:线性模型
线性模型 线性模型的基本形式为: f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法,得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...
如何通过git命令查看项目连接的仓库地址?
要通过 Git 命令查看项目连接的仓库地址,您可以使用以下几种方法: 1. 查看所有远程仓库地址 使用 git remote -v 命令,它会显示项目中配置的所有远程仓库及其对应的 URL: git remote -v输出示例: origin https://…...
