Spring项目整合策略模式~实战应用

需求背景

1、在管控流程中,涉及到的业务操作很多,不同的业务具有不同的策略实现
举个具体的例子:
在比价管控流程中,有比价策略和管控策略,每个业务的比价和管控均不一样。因此使用策略模式来开发

整体架构流程

1、定义业务策略枚举: 比价 和 管控

/**
 * @description:
 * @author: hongbin.zheng
 * @create: 2023-07-17 16:33
 **/
public enum StrategyType {
	priceCompare,

	priceControl
	;
}

2、定义业务策略注解,标注出 策略的类

/**
 * @description:
 * @author: hongbin.zheng
 * @create: 2023-07-17 16:34
 **/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
@Component
@Inherited
public @interface StrategyAnnotation {
	/**
	 * 策略类型
	 */
	StrategyType[] strategyType();

	/**
	 * 具体的策略建
	 */
	String[] dataType() default {};
}

3、定义策略基本方法

/**
 * @description:
 * @author: hongbin.zheng
 * @create: 2023-07-17 16:46
 **/
public interface PriceCompareStrategy {
	/**
	 * 执行价格比价
	 */
	public String doPriceCompare();
}



/**
 * @description:
 * @author: hongbin.zheng
 * @create: 2023-07-17 16:52
 **/
public interface PriceControlStrategy {
	/**
	 * 执行管控
	 * @return
	 */
	public String doPriceControl();
}

4、写每个具体实现的策略类

/**
 * @description:
 * @author: hongbin.zheng
 * @create: 2023-07-17 16:44
 **/
@Service
@StrategyAnnotation(strategyType = StrategyType.priceCompare, dataType = "firstPriceCompare")
public class FirstPriceCompareStrategy implements PriceCompareStrategy {
	@Override
	public String doPriceCompare() {
		System.out.println("-------first price compare start---------");
		System.out.println("-------do do do ---------");
		System.out.println("-------first price compare end---------");
		return "first price compare end";
	}
}


/**
 * @description:
 * @author: hongbin.zheng
 * @create: 2023-07-17 16:50
 **/
@Service
@StrategyAnnotation(strategyType = StrategyType.priceCompare, dataType = "secondPriceCompare")
public class SecondPriceCompareStrategy implements PriceCompareStrategy {
	@Override
	public String doPriceCompare() {
		System.out.println("-------second price compare start---------");
		System.out.println("-------do do do ---------");
		System.out.println("-------second price compare end---------");
		return "second price compare end";
	}
}

/**
 * @description:
 * @author: hongbin.zheng
 * @create: 2023-07-17 16:53
 **/
@Service
@StrategyAnnotation(strategyType = StrategyType.priceControl, dataType = "firstPriceControl")
public class FirstPriceControlStrategy implements PriceControlStrategy {
	@Override
	public String doPriceControl() {
		System.out.println("---------do first price control start ---------------");
		System.out.println("---------do first price control end ---------------");
		return "do first price control end";
	}
}



/**
 * @description:
 * @author: hongbin.zheng
 * @create: 2023-07-17 16:53
 **/
@Service
@StrategyAnnotation(strategyType = StrategyType.priceControl, dataType = "secondPriceControl")
public class SecondPriceControlStrategy implements PriceControlStrategy {
	@Override
	public String doPriceControl() {
		System.out.println("---------do second price control start ---------------");
		System.out.println("---------do second price control end ---------------");
		return "do second price control start";
	}
}

@Service
@StrategyAnnotation(strategyType = {StrategyType.priceCompare, StrategyType.priceControl}, dataType = "commonStrategy")
public class PriceCompareAndControlStrategy implements PriceCompareStrategy, PriceControlStrategy {
	@Override
	public String doPriceCompare() {
		System.out.println("-------common price compare start---------------");
		System.out.println("-------common price compare end---------------");
		return "common price compare end";
	}

	@Override
	public String doPriceControl() {
		System.out.println("-------common price control start---------------");
		System.out.println("-------common price control end---------------");
		return "common price control end";
	}
}

5、编写策略管理类,管理所有的策略,并且对外暴露出 拿到具体策略类的方法

package com.dgut.strategy.springboot_strategy;

import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * @description:
 * @author: hongbin.zheng
 * @create: 2023-07-17 16:59
 **/
@Service
public class StrategyServiceManager {
	@Autowired
	private ApplicationContext context;
	/**
	 * 存储策略:类型:具体实现类
	 */
	private Map<StrategyType, Map<String, Object>> map;

	public <E> E getStrategyInstance(StrategyType strategyType, String type, Class<E> eClass) {
		Map<String, Object> strategyTypeMap = map.get(strategyType);
		if (strategyTypeMap != null && !map.isEmpty()) {
			Object bean = strategyTypeMap.get(type);
			if (bean != null) {
				return eClass.cast(bean);
			}
		}
		return null;
	}

	@PostConstruct
	private void init() {
		map = Maps.newHashMap();

		Map<String, Object> beans = context.getBeansWithAnnotation(StrategyAnnotation.class);
		for (Object value : beans.values()) {
			StrategyAnnotation annotation = value.getClass().getAnnotation(StrategyAnnotation.class);
			StrategyType[] strategyTypes = annotation.strategyType();
			String[] dataTypes = annotation.dataType();
			if (strategyTypes == null || strategyTypes.length == 0 || dataTypes == null || dataTypes.length == 0) {
				throw new RuntimeException("注解上必填字段不能为空");
			}

			for (StrategyType strategyType : strategyTypes) {
				for (String dataType : dataTypes) {
					map.computeIfAbsent(strategyType, k -> Maps.newHashMap()).put(dataType, value);
				}
			}
		}
	}

}

6、代码流程测试

package com.dgut.strategy.springboot_strategy;

import com.dgut.strategy.springboot_strategy.compare.PriceCompareStrategy;
import com.dgut.strategy.springboot_strategy.control.PriceControlStrategy;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @description:
 * @author: hongbin.zheng
 * @create: 2023-07-18 16:17
 **/
@SpringBootTest
public class StrategyTest {
	@Autowired
	private StrategyServiceManager strategyServiceManager;

	@Test
	public void test2() {
		String strategyName = "priceControl";
		String dataType = "firstPriceControl";
		System.out.println(priceControlTest(strategyName, dataType));
		String dataType2 = "secondPriceControl";
		System.out.println(priceControlTest(strategyName, dataType2));

		String dataType3 = "commonStrategy";
		System.out.println(priceControlTest(strategyName, dataType3));


	}
	public String priceControlTest(String strategyName, String dataType) {
		StrategyType strategyType = StrategyType.valueOf(strategyName);
		if (strategyType == null) {
			return "管控策略不存在";
		}
		PriceControlStrategy strategyInstance = strategyServiceManager
				.getStrategyInstance(strategyType, dataType, PriceControlStrategy.class);
		if (strategyInstance == null) {
			return "找不到管控策略";
		}

		return strategyInstance.doPriceControl();
	}


	@Test
	public void test() {
		String strategyName = "priceCompare";
		String dataType = "firstPriceCompare";
		System.out.println(priceCompareTest(strategyName, dataType));
		String dataType2 = "secondPriceCompare";
		System.out.println(priceCompareTest(strategyName, dataType2));

		String dataType3 = "commonStrategy";
		System.out.println(priceCompareTest(strategyName, dataType3));
	}

	public String priceCompareTest(String strategyName, String dataType) {
		StrategyType strategyType = StrategyType.valueOf(strategyName);
		if (strategyType == null) {
			return "策略不存在";
		}
		PriceCompareStrategy strategyInstance = strategyServiceManager
				.getStrategyInstance(strategyType, dataType, PriceCompareStrategy.class);
		if (strategyInstance == null) {
			return "找不到比价策略";
		}

		return strategyInstance.doPriceCompare();
	}
}

技术细节

通过spring的context对象,解析获取类注解,拿到bean,常规操作,这个要学起来,很多地方可以这样子操作呢。

总结

知道的越多,不知道的越多,希望对你有帮助! \color{red}知道的越多,不知道的越多,希望对你有帮助! 知道的越多,不知道的越多,希望对你有帮助!

你可能感兴趣的:(23种设计模式,策略模式)