600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Java设计模式之3种策略模式实现

Java设计模式之3种策略模式实现

时间:2023-08-11 00:18:35

相关推荐

Java设计模式之3种策略模式实现

一、什么是策略模式

所谓策略模式,就是定义了一组策略,分别封装在不同类中,每种策略都可以根据当前场景相互替换,从而使策略的变化可以独立于操作者。比如我们要去某个地方,会根据距离的不同来选择不同的出行方式,比如:共享单车、打车、坐飞机等等,这些出行方式即不同的策略。

二、为什么使用策略模式

我们在平时为了快速完成业务需求,会在代码实现时大量使用if…else,但当代码中大量充实着这种结构时会使代码的可读性、维护性降低并更容易出错。策略模式是解决这种问题的好办法,它符合设计模式中的开闭原则。

三、策略模式的组成

3.1 结构

3.2 角色

Context(环境类)

策略上下文,维护一个Strategy对象的引用,屏蔽上层模块对策略、算法的直接访问Strategy(抽象策略类)

这是一个抽象角色,定义了所有的具体策略类所需的接口ConcreteStrategy(具体策略类)

实现了在抽象策略类中定义的方法,封装了相关的算法或行为。根据多态的特性,在运行时,具体策略类将覆盖在环境类中定义的抽象策略累对象

四、如何实现策略模式

源代码:/mofan3/strategy-mode.git

4.1 基于注解实现

枚举定义

/*** 消息类型枚举*/@Getter@AllArgsConstructorpublic enum MessageType {PUSH("通知栏"),SMS("短信"),EMAIL( "邮件"),WECHAT( "微信"),DING_DING_ROBOT( "钉钉机器人"),DING_DING_WORK_NOTICE("钉钉工作通知");/*** 描述*/private String description;}

注解定义

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Componentpublic @interface HandlerAnnotation {MessageType type();}

策略接口定义

public interface BizHandler {void execute(MessageInfo messageInfo);}

策略实现

@HandlerAnnotation(type = MessageType.SMS)@Slf4jpublic class SmsHandler implements BizHandler {@Overridepublic void execute(MessageInfo messageInfo) {SmsMessageInfo smsMessageInfo = (SmsMessageInfo) messageInfo;// 发送短信log.info("发送短信消息:{}",smsMessageInfo.getContent());}}

@HandlerAnnotation(type = MessageType.WECHAT)@Slf4jpublic class WeChatHandler implements BizHandler {@Overridepublic void execute(MessageInfo messageInfo) {WeChatMessageInfo weChatMessageInfo = (WeChatMessageInfo) messageInfo;// 发送微信log.info("发送微信消息:{}",weChatMessageInfo.getContent());}}

策略组装

@Componentpublic class BizHandlerContext implements BeanPostProcessor {private final Map<String, BizHandler> bizHandlerMap = new HashMap<>();@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {HandlerAnnotation annotation = AnnotationUtils.findAnnotation(bean.getClass(), HandlerAnnotation.class);if (ClassUtils.isAssignableValue(BizHandler.class,bean) && annotation != null) {bizHandlerMap.put(annotation.type().name(), (BizHandler)bean);}return bean;}public BizHandler getBizHanler(String type) {BizHandler bizHandler = this.bizHandlerMap.get(type);if (bizHandler == null) {throw new RuntimeException("not.found.BizHandler");}return bizHandler;}}

BizHandlerContext类实现BeanPostProcessor接口,在postProcessBeforeInitialization(…)方法中拿到所有含有@HandlerAnnotation注解的bean,以bean的注解中的type值作为键和bean作为值构建handlerMap,从而在外界以type作为请求时可以准确的获取到handlerMap中相应的bean。

测试

@SpringBootTestclass StrategyModeApplicationTests {@AutowiredBizHandlerContext bizHandlerContext;@Testvoid contextLoads() {AbstractBizHandler bizHanler = bizHandlerContext.getBizHanler(MessageType.SMS.name());SmsMessageInfo smsContentModel = new SmsMessageInfo();smsContentModel.setContent("【XXX】验证码:313122,您正在进行登录操作,若非本人操作,请勿泄露");bizHanler.execute(smsContentModel);}}

4.2 基于@Autowired的实现

策略接口定义

public interface BizHandler {void execute(MessageInfo messageInfo);String getType();}

策略实现

@Service@Slf4jpublic class SmsHandler implements BizHandler {@Overridepublic void execute(MessageInfo messageInfo) {SmsMessageInfo smsMessageInfo = (SmsMessageInfo) messageInfo;// 发送短信log.info("发送短信消息:{}",smsMessageInfo.getContent());}@Overridepublic String getType() {return MessageType.SMS.name();}}

@Service@Slf4jpublic class WeChatHandler implements BizHandler {@Overridepublic void execute(MessageInfo messageInfo) {WeChatMessageInfo weChatMessageInfo = (WeChatMessageInfo) messageInfo;// 发送微信log.info("发送微信消息:{}",weChatMessageInfo.getContent());}@Overridepublic String getType() {return MessageType.WECHAT.name();}}

策略组装

@Componentpublic class BizHandlerContext{private final Map<String, BizHandler> bizHandlerMap = new HashMap<>();@Autowired(required = false)public void putBizHandler(List<BizHandler> bizHandlerList) {for (BizHandler bizHandler : bizHandlerList) {String type = bizHandler.getType();if (StringUtils.isEmpty(type)) {throw new IllegalArgumentException("BizHandler name must not be empty");}bizHandlerMap.put(type, bizHandler);}}public BizHandler getBizHanler(String type) {BizHandler bizHandler = this.bizHandlerMap.get(type);if (bizHandler == null) {throw new RuntimeException("not.found.BizHandler");}return bizHandler;}}

BizHandlerContext使用了Spring的@Autowired注解按照类型自动装配的功能,循环遍历BizHandler集合,获取type值作为键和bean作为值加入到handlerMap中。

测试

@SpringBootTestclass StrategyModeApplicationTests {@AutowiredBizHandlerContext bizHandlerContext;@Testvoid contextLoads() {AbstractBizHandler bizHanler = bizHandlerContext.getBizHanler(MessageType.SMS.name());SmsMessageInfo smsContentModel = new SmsMessageInfo();smsContentModel.setContent("【XXX】验证码:313122,您正在进行登录操作,若非本人操作,请勿泄露");bizHanler.execute(smsContentModel);}}

4.3 基于InitializingBean的实现

抽象处理器定义

public abstract class AbstractBizHandler implements InitializingBean {@Autowiredprivate BizHandlerContext bizHandlerContext;@Overridepublic void afterPropertiesSet() throws Exception {bizHandlerContext.putBizHandler(getType(),this);}public abstract void execute(MessageInfo messageInfo);public abstract String getType();}

InitializingBean接口为bean提供了属性初始化后的处理方法,它只包括afterPropertiesSet方法。也可用@PostConstruct注解实现,但接口实现方式在调用效率上高一些,@PostConstruct是通过反射机制调用的

策略实现

@Service@Slf4jpublic class SmsHandler extends AbstractBizHandler {@Overridepublic void execute(MessageInfo messageInfo) {SmsMessageInfo smsMessageInfo = (SmsMessageInfo) messageInfo;// 发送短信log.info("发送短信消息:{}",smsMessageInfo.getContent());}@Overridepublic String getType() {return MessageType.SMS.name();}}

@Service@Slf4jpublic class WeChatHandler extends AbstractBizHandler {@Overridepublic void execute(MessageInfo messageInfo) {WeChatMessageInfo weChatMessageInfo = (WeChatMessageInfo) messageInfo;// 发送微信log.info("发送微信消息:{}",weChatMessageInfo.getContent());}@Overridepublic String getType() {return MessageType.WECHAT.name();}}

策略组装

@Componentpublic class BizHandlerContext{private final Map<String, AbstractBizHandler> bizHandlerMap = new HashMap<>();public void putBizHandler(String type, AbstractBizHandler handler) {bizHandlerMap.put(type, handler);}public AbstractBizHandler getBizHanler(String type) {AbstractBizHandler bizHandler = this.bizHandlerMap.get(type);if (bizHandler == null) {throw new RuntimeException("not.found.BizHandler");}return bizHandler;}}

测试

@SpringBootTestclass StrategyModeApplicationTests {@AutowiredBizHandlerContext bizHandlerContext;@Testvoid contextLoads() {AbstractBizHandler bizHanler = bizHandlerContext.getBizHanler(MessageType.SMS.name());SmsMessageInfo smsContentModel = new SmsMessageInfo();smsContentModel.setContent("【XXX】验证码:313122,您正在进行登录操作,若非本人操作,请勿泄露");bizHanler.execute(smsContentModel);}}

五、总结

通过策略设计模式的使⽤可以把我们方法中的if语句优化掉,以上3种实现方式本质上是利用Map的key-value结构做映射来解决⼤量if else 的叠加嵌套问题,⼤量的if语句使用会让代码难以扩展,也不好维护,同时在后期遇到各种问题也很难维护。在使用这样的设计模式后可以很好的满⾜隔离性与和扩展性,对于不断新增的需求也⾮常⽅便承接。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。