通过反射机制实现一个完美的策略模式

反射第二弹:用注册器动态注册(用自定义的注解标注的)策略,实现策略模式的设计 Java的反射机制允许程序在运行时检查和操作类、方法和字段。通过反射,你可以在运行时获取类的信息(如类名、字段、方法等),并且可以动态地创建对象、调用方法和访问/修改字段。以下是Java反射机制的一些重要概念和用法:class类: Java中的每个类都有一个与之关联的Class对象,它包含了该类的完整信息。Class 阅读详情
AI摘要

本文深入探讨了策略模式在加密算法工具类中的应用,通过引入反射和Map,实现了动态选择加密算法的功能,同时保持了代码的开闭原则。最终,通过字符串参数实现了算法的选择,简化了客户端代码。

一、前言

最近打算在自己的项目中加上一个加密算法工具类,用来调用不同的加密算法,并且希望能够符合开闭原则,本来打算用《大话设计模式》中讲解的策略模式,但是对书中的实例不太满意,但是书中介绍了想要实现一个更好的策略模式需要用到java的反射机制,所以开始学习如何用策略模式实现一种好用的加密算法工具类。

二、解决思路与实现

先来看一下策略模式的模型图:

在上图的策略模式原型中,可以看出来,我们如果想要用ConcreteStrategyA的算法的话就需要在客户端代码中实例化一个ConcreteStrategyA对象并将其注入到Context对象中,代码如下:

public static void main(String[] arg){
    Context context = new Context(new ConcreteStrategyA());
    context.algorithm();
}

其中Context类代码如下:

public class Context{
    private Strategy strategy;
    public Context(Strategy strategy){
        this.strategy = strategy;
    }
    
    public String algorithm(String content){
        return strategy.algorithm(content);
    }

}

A.策略模式变种 --- 通过反射实现

上面的原型策略模式抛去客户端代码的话会是一个完美的模式,但是恰恰因为客户端代码这一块,我很嫌弃自己每次用的时候都要实例化对象的这种方式,于是我就像能不能换一种方式不用我进行实例化同时代码又能符合开闭原则,于是自然而然的就想到了java的反射机制,改变后的Context类代码如下:

public class Context {
	public static String algorithm(Class<? extends Strategy> c, String content) {
		Strategy strategy = null;
		try {
			strategy = c.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return strategy.algorithm(content);
	}
}

客户端代码:

public static void main(String[] args) {
		String content = Context.algorithm(ConcreteStrategyA.class, "haha");
		System.out.println(content);
	}

github项目地址:https://github.com/codeHaoHao/strategyTest,项目中test1包中为这个实例代码

 

B、策略模式变种 -- 加入Map

加入map这种方式相当于加入了一个缓存,把实例化后的对象缓存起来不用再次被实例化,因为我的业务上算法类会被经常调用,因此我将实例化的算法对象缓存起来,避免重新实例化产生过多的瞬时内存垃圾,实现的Context代码如下:

public class Context {
	
	private static Map<String, Strategy> map = new ConcurrentHashMap<String, Strategy>();
	
	public static String algorithm(Class<? extends Strategy> c, String content) {
		Strategy strategy = null;
		try {
			if (map.get(c.getName()) != null) {
				System.out.println("from map");
				strategy = map.get(c.getName());
			} else {
				System.out.println("from class.newInstance");
				strategy = c.newInstance();
				map.put(c.getName(), strategy);
			}
			
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return strategy.algorithm(content);
	}
}

之所以使用ConcurrentHashMap而不使用HashMap是为了避免使用HashMap扩容时会产生的线程不安全问题。

客户端代码:

public static void main(String[] args) {
		String content = Context.algorithm(ConcreteStrategyA.class, "haha");
		System.out.println(content);
}

github代码:https://github.com/codeHaoHao/strategyTest/tree/master/src/test2

C、策略模式变种 -- 最终版

其实通过上面的两次策略模式变种这个算法工具类Context变得好用了很多,当我创建一个新的算法实现Strategy接口时不再需要向Context类中添加什么东西,符合开闭原则,同时客户端代码也不需要做出改变,只需要传入不同的Class对象即可。

但是我还是嫌弃每次用的使用需要传入一个Class对象,并不是很喜欢这种方式,我希望能让我每次使用的时候传入一个字符串,然后根据不同的字符串执行不同的算法,而且我还希望这个算法工具类能够符合开闭原则,即Context类中需要一个algorithm方法能够根据传入字符串的不同执行不同的算法,同时我新加算法ConcreteStrateC类的时候不需要改变这个Context类中的任何代码,如此便能实现一个完美的策略模式。

思路:

既然只传字符串,该字符串还不能用类常量,因为用了类常量就意味着每次新加一个算法就得重新新加一个类常量,因此想到可以用类名称,只要我能获取到这个类的Class对象,那么我就能获取到类类名称。但是新的问题我怎么获取到这个类的Class对象,我还不能传递Class对象,因此只能另辟蹊径,从这些类的接口开始,因为这些类都实现了一个抽象接口Strategy,那么我只要能获取到这个接口的所有实现就可以了,我写了一个ClassUtils工具类用来获取指定接口的实现,请看文章  java找到指定接口的实现类

只要能根据指定接口找到其实现类,那一切就都简单了,看具体Context实现:

public class Context {
	// 存储类实例,key为类名,value为实例
	private static Map<String, Strategy> map;
	static {
		List<Object> strategys = null;
		try {
			strategys = ClassUtils.getAllObjectByInterface(Strategy.class);
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		map = new HashMap<String, Strategy>();
		for (int i = 0; i < strategys.size(); i++) {
			Strategy strategy = (Strategy) strategys.get(i);
			String name = strategy.getClass().getSimpleName(); // 获取类名
			map.put(name, strategy);
		}
	}
	
	public static String algorithm(String className, String content) {
		return map.get(className).algorithm(content);
	}
}

客户端代码:

public static void main(String[] args) {
		String content = Context.algorithm("ConcreteStrategyA", "haha");
		System.out.println(content);
	}

GitHub代码:https://github.com/codeHaoHao/strategyTest/tree/master/src/test3

从客户端代码可以看出我们不再需要传递一个Class对象了,我们现在只需要传递一个类名就可以了,并且当我们新加一个ConcreteStrategyC类的时候,我们不需要对Context类进行任何修改,完美。

三、总结

经过这次的对策略模式的深入思考与学习,对设计模式有了更深的认识,很多设计模式还有可以优化的地方,需要自己去摸索学习,加油。

 

 

 

 

策略模式的实现,通过反射 策略模式代码,两种方式实现,第一种,通过map存储方式,第二种,通过配置文件加反射方式 立即下载

相关推荐

2025年VSCode AI插件实战:如何用Devika+Continue+Tabby三件套10倍提升开发效率

本文详细介绍了2025年VSCode AI插件Devika、Continue和Tabby的三件套组合,如何通过智能开发工作流10倍提升开发效率。从项目架构生成到上下文感知辅助,再到本地化智能编码,这套方案实现了从需求分析到代码生成的全流程自动化,特别适合中大型项目开发。

weixin_26911099的博客 270

策略模式+反射/spring容器 代替if-else或switch-case

策略模式+工厂模式+反射/Spring容器 来代替业务中繁杂的if-else 或switch-case

weixin_44325982的博客 904

告别概念晕眩:用TC3xx SMU和TLF35584的配置实例,搞懂ASIL D功能安全落地

本文通过英飞凌TC3xx系列MCU的SMU模块与TLF35584电源管理芯片的协同配置实例,详细解析了如何实现符合ASIL D功能安全标准的刹车辅助ECU。文章涵盖SMU报警源配置、响应动作类型、TLF35584的安全状态管理,以及构建完整安全闭环的实践方法,帮助工程师将抽象的安全概念落地为具体设计方案。

weixin_30647065的博客 436

Java反射机制与应用

Java的反射机制提供了运行时分析处理类的能力。Spring框架的IOC容器使用了反射技术,可以简化代码编写。

欢迎关注公众号“雨林寻北”,添加个人微信codetrend(备注技术)。 330

[DA45] 使用PageRank算法分析希拉里邮件中的人物关系

一. 相关知识 (一) PageRank算法 PageRank 算法是 google 公司的创始人拉里·佩奇和谢尔·盖布林于1998年提出的网页搜索优化算法. 详细内容请见百度百科:google pagerank. 如果你了解了该算法, 就能明白上一段的超链接从本页面链出, 链入百度百科的 PageRank 算法页面增加了该页面...

Vincent_Chu的博客 2377

Python实战:用NumPy实现LU分解与QR分解(附代码对比)

本文深入探讨了使用NumPy实现LU分解与QR分解的实战方法,通过代码对比分析了两种矩阵分解技术的原理、数值稳定性差异及核心应用场景。LU分解适用于高效求解线性方程组,而QR分解凭借其正交化特性,在求解最小二乘问题和处理病态矩阵时更具优势。文章提供了详细的Python代码示例,帮助开发者根据具体问题选择最合适的分解方法。

php55的博客 1212

Spring反射+策略模式Demo

代码耦合性太高,每加一个宠物则需要再service中的静态代码块添加实例从而导致,我们如果忘记加了,则实现不了新宠物的陪玩。也违反了类的开闭原则。通过使用spring反射实现策略模式,简化了代码,也让开发人员更专注的写业务代码了,这样如果我们增加了一个其他宠物的情况下,也只需要增加一个实现类就可以了。

程序员高级码农的博客 623

有了网段为什么还要有VLAN???

近几日,在学习VLAN及VXLAN方面的知识,对于产生原因做一个总结及详解。 VLAN(Virtual Local Area Network,虚拟局域网),其主要用途是用来缩小广播域,即进行隔离。 先对广播域的一个概念做如下描绘:如下图,主机A、B、C、D均连接在交换机SW1上,其中A、C同网段为192.168.252网段,而B和D同网段,为192.168.250网段。 现,假如A与C第...

dandandean_96的博客 6885

java设计模式实战-(反射+策略模式)

学完23种设计模式,相信很多同学都疑问,除了单例模式、工厂模式其他模式还有运用的场景吗? 现在这里就举一个例子。 首先策略模式需要先有了解,我们常用策略模式解决实际开发中的if else特别多的场景。但是在实际的开发中,真正单独只用策略模式的场景还是很少的。我们需要利用Spring的注入功能,实现根据不同的入参,跳转到不同的实现类中,以此来减少if else的使用。 举个场景:假如我们做物流系统,需要根据前段传过来的渠道参数,来定制化不同的规则校验逻辑。这里我们距离alibaba渠道和wechat渠道

去武帝城,战王仙芝 1646

deepstream车道线检测自定义插件化,其中要注意pipeline的配置,如果插件位置配置不对,会报input format should be RGBA when using blur-obje

以上代码中,我们先从对象池中获取一个 DsUserMeta 对象,然后使用 get_lane_line_from_frame 函数获取车道线检测结果,并使用 add_lane_line_meta 函数将其添加到 DsUserMeta 对象中。注意,上述代码中的 get_lane_line_from_frame 函数和 add_lane_line_meta 函数需要你自己实现,用于从视频帧中提取车道线检测结果,并将其添加到 DsUserMeta 中。

pvmsmfchcs的博客 690

2026年软件测试职业院校技能大赛—ERP管理平台-采购入库模块Bug定位与查找

竞赛对接软件测试相关标准,以“ERP管理平台” 为被测系统,围绕软件测试领域的主流技术及工具,考查选手面 对实际问题的综合分析能力,对测试文档、测试用例的设计能力, 对单元测试、自动化测试、性能测试、接口测试等测试工具及方 法的掌握程度,检验选手团队协作能力、组织规划能力、方法运用能力等。

我是网络安全兼技能大赛工程师,专注网络安全技术学习与技能大赛实战!持续分享最新的技术文章,帮你少走弯路,一起在技术赛道上进步~ 195

通过反射+策略模式实现筛选集合中符合条件的数据

遇到这样一种业务:存在产品信息、公司信息等多种维度的表数据,每种维度的数据都会对应一套查询规则且查询规则是可配可扩展的,查询规则就类似于sql中写where,要实现恒等、模糊、范围等查询规则;因表数据量很大,而且存在很多复杂的查询,所以就设计了一套在java集合中筛选数据的功能;

Ironhide的博客 972

Unity-Mirror网络框架-从入门到精通之Mirror简介

在现代游戏开发中,网络功能日益成为提升游戏体验的关键组成部分。Mirror是一个用于Unity的开源网络框架,专为多人游戏开发设计。它使得开发者能够轻松实现网络连接、数据同步和游戏状态管理。本文将深入介绍Mirror的基本概念、如何与其他网络框架进行比较,以及如何从零开始创建一个使用Mirror的简单网络项目。Mirror是一个功能强大的Lite网络框架,旨在替代Unity的UNet网络解决方案。它提供了高效的多玩家架构、简单易用的API,以及良好的社区支持。

TxNet 3089

工厂模式+策略模式+反射机制解决系统功能模块相似的问题

工厂模式+策略模式+反射机制解决系统功能模块相似的问题

weixin_39503283的博客 1599

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

JAVA设计模式之策略模式详解

策略模式(strategy pattern)的原始定义是:定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式让算法可以独立于使用它的客户端而变化。其实我们在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,出行旅游可以乘坐飞机、乘坐火车、骑自行车或自己开私家车等。

励志成为一名优秀的全能型软件开发工程师。 1万+

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

策略模式及用例

策略模式用于算法的自由切换和扩展,对应于解决某一问题的一个算法族,允许用户从该算法族中任选一个算法解决某一问题,同时可以方便地更换算法和增加新的算法。策略模式实现了算法定义和算法使用的分离,它通过继承和多态的机制实现对算法族的使用和管理,是一个简单,实用的设计模式。策略模式的定义如下:策略模式又称为政策(Policy)模式,它是一种对象行为型模式。

weixin_46140858的博客 2201

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

设计模式-策略模式

111

排长性感的小屁屁 1900

java策略模式+反射机制+枚举,似乎可以完全取代if else

在我看来: ······策略模式的优点是:拓展方便+不影响原有代码+可以提取公共方法,减少代码冗余 ······将反射放进策略模式的优点是:可以自动创建对象,不用手动创建 ······将枚举放进策略模式的优点是:枚举可以存储多个属性值 本方案拓展的用法: ······只用增加策略的实现类,和枚举类 下面是代码,多看注释,都在注释里 代码大概实现的功能是,2个不同的会员实现不同的折扣 首先是会员的枚举类 public enum UserPlayServiceEnum { //会员类型,会员实现类名,会员

weixin_44289552的博客 943

java找到指定接口的实现类

一、背景 想在自己开发的项目上加一个算法工具类用来整合不同的算法,并且要求低耦合符合开闭原则,于是想到了《大话设计模式》里的策略模式,但是书中的策略模式还没有达到完全符合开闭原则,同时我在文章结尾看见说可以运用反射机制来大幅降低代码的耦合度,因此开始在学习如何实现,在学习过程中发现需要写一个方法用来找到指定接口的实现类,因此开启了这趟学习之旅。 二、寻求答案的路途 刚开始看到根据指定接...

codeHaoHao的博客 1万+

【策略模式】if...else if...看花眼,策略模式当首选

if/switch条件语句太多了,来看看设计模式中的策略模式

P_newbie的博客 940

Spring+策略模式+反射+泛型=无策略模式?

为什么要用策略模式?何时用策略模式? 策略模式根据教科书式中的介绍为定义一系列算法,把它们一个个封装起来,并且使它们之间可互相替换,从而让算法可以独立于使用它的用户而变化。 在实际业务开发中,算法一般表现为一系列特定的业务操作,根据特定的业务策略执行相应的“算法”。一般在以下场景可以考虑使用策略模式: 选择语句(如if/else、switch)的多,选择执行块中操作各不相同且之后可能会进行业务扩展 避免选择语句导致的难以维护 想提高代码逼格 自定义式的策略模式演变 策略模式1.0 - 教材式的使用过程

z28126308的专栏 1303

浅谈设计模式之策略模式

浅谈设计模式之策略模式 什么是策略模式 策略模式是指针对同一个行为定义不同的算法(或者操作),而且这些算法都可以相互替换,对于使用者来说可以不关心具体的算法实现,让算法独立于使用它的客户。 举例实现 需求 假如我们有一个会员系统系统,同一间商品不同的会员等级有不同的会员折扣,比如: 钻石会员:8折 铂金会员:8.5折 黄金会员:9折 白银会员:9.5折 普通会员:不打折 类图 代码实现 具体商品iphone类: public class Iphone { private BigDecimal

jiangzhou556的博客 213

设计模式之【策略模式】(java实现)

策略模式(strategy pattern)的原始定义是:定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式让算法可以独立于使用它的客户端而变化。在软件开发中,经常会遇到这种情况,开发一个功能可以通过多个算法去实现,我们可以将所有的算法集中在一个类中,在这个类中提供多个方法,每个方法对应一个算法,或者我们也可以将这些算法都封装在一个统一的方法中,使用if…else…等条件判断语句进行选择。但是这两种方式都存在硬编码的问题,后期需要增加算法就需要修改源代码,这会导致代码的维护变得困难。

qq_22772699的博客 646

策略模式及优化

策略模式是一种行为设计模式,通过将算法封装为独立类实现定义与使用的分离。核心组件包括策略接口、具体策略类、上下文和客户端,支持运行时动态切换算法。该模式符合开闭原则,消除条件语句,适用于多种算法切换场景(如排序、支付方式等)。优化方案引入策略工厂和反射机制,通过注册管理实现自动创建和高效切换。代码示例展示了C++实现,通过上下文类动态调用不同排序算法,验证了策略模式的灵活性和扩展性。

eatbaozi的博客 738
上一篇: java找到指定接口的实现类
下一篇: Mac安装配置Mysql
Mr.LiJiaHao
博客等级 码龄10年 27粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值