策略模式与Spring最佳实践

本文介绍了如何在Spring中优雅地实现策略模式,用于灵活对接不同的下单渠道(如MQ)和消息通知方式(如短信)。通过策略接口、策略类、策略容器和策略使用方,构建了一个可扩展的系统。示例代码展示了具体实现,包括策略接口、策略类的实现、策略注册和策略容器的创建。在测试中,展示了如何根据需求选择合适的策略进行消息发送。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

在工作中大家肯定会用到策略模式,比如对接不同种类的下单渠道,不同种类的消息通知(短信,mq等)今天就给大家带来一种自认为与Spring结合比较好的实现模式,这种模式的实现得益于同事的指导,今天就分享给大家,期待与大家的共同进步。

策略模式的定义

一组可以相互替换的算法簇,可以供大家根据一定的规则来选择相对应的策略来使用。

策略模式的组成

策略模式一般由以下三个部分组成

  • 策略(Strategy):一般都会有个Strategy接口,然后具体的策略都实现Strategy的接口都是策略类;
  • 策略容器(Context):存放具体的策略的地方(可以类比古时候装妙计的锦囊);
  • 决策策略引擎(策略使用方client) :通过一定的规则来选择具体执行的策略。
策略模式实战编码
  • 首先给大家看一下项目的结构示意图
    在这里插入图片描述

  • 其次,再给大家看一下主要类之间的关系图
    在这里插入图片描述

  • StrategyService类是是策略接口类,KafkaStrategyServiceImpl和SmsStrategyServiceImpl是具体的策略类

  • StrategyServiceFactory相当于策略容器,存放策略规则与策略的对应关系

具体的代码实现如下
/**
* 策略接口类
**/
public interface StrategyService {
 void sendMessage(String context);
}

具体的策略实现类SmsStrategyServiceImpl

import com.example.demo.strategy.ForStrategyType;
import com.example.demo.strategy.StrategyService;
import com.example.demo.strategy.StrategyType;
import org.springframework.stereotype.Service;
@Service
@ForStrategyType(
 StrategyType.SMS
)
public class SmsStrategyServiceImpl implements StrategyService {
	 @Override
	 public void sendMessage(String context) {
	 System.out.println("sms:"+context);
	 }
}

具体实现策略类KafkaStrategyServiceImpl

import com.example.demo.strategy.ForStrategyType;
import com.example.demo.strategy.StrategyService;
import com.example.demo.strategy.StrategyType;
import org.springframework.stereotype.Service;
@Service
@ForStrategyType(
 StrategyType.MQ
)
public class KafkaStrategyServiceImpl implements StrategyService {
	 @Override
	 public void sendMessage(String context) {
	 System.out.println("mq:"+context);
	 }
}

策略注册注解类

package com.example.demo.strategy;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface ForStrategyType {
 StrategyType[] value();
}

策略注册枚举类

package com.example.demo.strategy;
public enum StrategyType {
	SMS(1,"短信"),
	MQ(2,"mq消息")
	;
	StrategyType(int code, String desc) {
	this.code = code;
	this.desc = desc;
	}
	private Integer code;
	private String desc;
	}

策略注册抽象工厂类

package com.example.demo.strategy;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
public abstract class AbstractEnumRegistryBuilder<E extends Enum> {
 public <T> Map<E, T> build(T[] beans) {
	 ImmutableMap.Builder<E, T> mapBuilder = ImmutableMap.builder();
	 for (T bean : beans) {
		 Class<?> builderClass = bean.getClass();
		 E[] keys = extractKeys(builderClass);
		 for (E key : keys) {
		 	mapBuilder.put(key, bean);
		 }
 }
 return mapBuilder.build();
 }
 public abstract E[] extractKeys(Class<?> builderClass);
}

策略具体注册工厂类

import com.google.common.base.Preconditions;
import org.springframework.stereotype.Component;
@Component
public class StrategyServiceRegistryBuilder extends AbstractEnumRegistryBuilder<StrategyType> {
 @Override
 public StrategyType[] extractKeys(Class<?> builderClass) {
	 ForStrategyType forStrategyType = builderClass.getAnnotation(ForStrategyType.class);
	 Preconditions.checkNotNull(forStrategyType, "Cannot find @StrategyType annotation on %s",
	 builderClass.getName());
	 return forStrategyType.value();
 }
}

策略容器类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class StrategyServiceFactory {
	 private final Map<StrategyType, StrategyService> messageServiceMap;
		 @Autowired
		 public StrategyServiceFactory(
		 
		 StrategyServiceRegistryBuilder strategyServiceRegistryBuilder,
		 StrategyService[] strategyServices) {
			 messageServiceMap = strategyServiceRegistryBuilder.build(strategyServices);
		 }
	 public StrategyService getMessageService(StrategyType strategyType){
	 
	 StrategyService strategyService = messageServiceMap.get(strategyType);
	 if(strategyService == null){
	 throw new RuntimeException("未能找到对应的处理类");
	 }
	 return strategyService;
	 }
}

策略的client

package com.example.demo;
import com.example.demo.strategy.StrategyType;
import com.example.demo.strategy.StrategyServiceFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
 @Autowired
 private StrategyServiceFactory strategyServiceFactory;
	 @Test
	 public void contextLoads() {
	 }
	 @Test
	 public void testStrategy(){
	 	strategyServiceFactory.getMessageService(StrategyType.SMS).sendMessage("Hello world");
	 }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值