总结一下之前的开发实践,参考网上开源项目实现的设计模式组件开发😊😊😊
封装构造者模式
Builder 模式,强调的是 管理依赖关系或者约束条件
构建者模式相对简单,仅需要提供一个抽象接口即可。构建者相关的特性均在实现类中完成。
java
package org.opengoofy.index12306.framework.starter.designpattern.builder;
import java.io.Serializable;
/**
* Builder 模式抽象接口
*
* @公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
*/
public interface Builder<T> extends Serializable {
/**
* 构建方法
*
* @return 构建后的对象
*/
T build();
}
封装责任链模式
什么是责任链:举个例子,SpringMvc 中可以定义拦截器,并且可以定义多个。当一个用户发起请求时,顺利的话请求会经过所有拦截器,最终到达业务代码逻辑,SpringMvc 拦截器设计就是使用了责任链模式
前置校验是非常重要的环节。下面是一个可能的校验步骤列表:
前置校验是非常重要的环节。下面是一个可能的校验步骤列表:
- 检查商品信息是否存在,包括商品名称、价格、规格等信息。
- 检查购买数量是否合法,是否超出了最大购买数量或最小购买数量的限制。
- 检查商品库存是否充足,以确保库存足够满足购买者的需求。
- 检查购买者的优惠券、积分等是否可以使用,以确保购买者能够享受相应的优惠或积分奖励。
- 检查收货地址信息是否完整和准确,以确保商品能够顺利地送达给购买者。
- 检查下单时间是否合法,例如检查购买者是否在限定的时间范围内下单。
首先定义一个处理器接口继承Spring 框架中的排序接口 Ordered。这将有助于保证责任链中的任务顺序执行。
csharp
public interface OrderCreateChainHandler<T> extends Ordered {
/**
* 执行责任链逻辑
*
* @param requestParam 责任链执行入参
*/
void handler(T requestParam);
}
创建多个具体的执行器对象,写处理逻辑
创建一个责任链上下文容器,用于存储与责任链相应的执行器对象:
typescript
/**
* 抽象责任链上下文
*
*/
public final class AbstractChainContext<T> implements CommandLineRunner {
private final Map<String, List<AbstractChainHandler>> abstractChainHandlerContainer = new HashMap<>();
/**
* 责任链组件执行
*
* @param mark 责任链组件标识
* @param requestParam 请求参数
*/
public void handler(String mark, T requestParam) {
List<AbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(mark);
if (CollectionUtils.isEmpty(abstractChainHandlers)) {
throw new RuntimeException(String.format("[%s] Chain of Responsibility ID is undefined.", mark));
}
abstractChainHandlers.forEach(each -> each.handler(requestParam));
}
@Override
public void run(String... args) throws Exception {
Map<String, AbstractChainHandler> chainFilterMap = ApplicationContextHolder
.getBeansOfType(AbstractChainHandler.class);
chainFilterMap.forEach((beanName, bean) -> {
List<AbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(bean.mark());
if (CollectionUtils.isEmpty(abstractChainHandlers)) {
abstractChainHandlers = new ArrayList();
}
abstractChainHandlers.add(bean);
List<AbstractChainHandler> actualAbstractChainHandlers = abstractChainHandlers.stream()
.sorted(Comparator.comparing(Ordered::getOrder))
.collect(Collectors.toList());
abstractChainHandlerContainer.put(bean.mark(), actualAbstractChainHandlers);
});
}
}
逻辑:在Spring程序启动后首先获取所有的AbstractChainHandler
执行器的实例,按照名称将实例保存到map中,然后遍历这个map,根据mark标识获取所有的这个执行器的集合,并按照顺序保存在map中
使用:将这个AbstractChainContext
注入到业务中,调用handler
方法来依次执行各个组件
封装策略模式
定义抽象策略处理接口,添加有返回值和无返回值接口。
csharp
package org.opengoofy.congomall.springboot.starter.designpattern.strategy;
/**
* 策略执行抽象
*/
public interface AbstractExecuteStrategy<REQUEST, RESPONSE> {
/**
* 执行策略标识
*/
String mark();
/**
* 执行策略
*
* @param requestParam 执行策略入参
*/
default void execute(REQUEST requestParam) {
}
/**
* 执行策略,带返回值
*
* @param requestParam 执行策略入参
* @return 执行策略后返回值
*/
default RESPONSE executeResp(REQUEST requestParam) {
return null;
}
}
添加策略选择器,通过订阅 Spring 初始化事件执行扫描所有策略模式接口执行器,并根据 mark 方法定义标识添加到 abstractExecuteStrategyMap
容器中。
客户端在实际业务中使用 AbstractStrategyChoose#choose
即可完成策略模式实现。
typescript
/**
* 策略选择器
*/
public class AbstractStrategyChoose implements ApplicationListener<ApplicationInitializingEvent> {
/**
* 执行策略集合
*/
private final Map<String, AbstractExecuteStrategy> abstractExecuteStrategyMap = new HashMap<>();
/**
* 根据 mark 查询具体策略
*
* @param mark 策略标识
* @return 实际执行策略
*/
public AbstractExecuteStrategy choose(String mark) {
return Optional.ofNullable(abstractExecuteStrategyMap.get(mark)).orElseThrow(() -> new ServiceException(String.format("[%s] 策略未定义", mark)));
}
/**
* 根据 mark 查询具体策略并执行
*
* @param mark 策略标识
* @param requestParam 执行策略入参
* @param <REQUEST> 执行策略入参范型
*/
public <REQUEST> void chooseAndExecute(String mark, REQUEST requestParam) {
AbstractExecuteStrategy executeStrategy = choose(mark);
executeStrategy.execute(requestParam);
}
/**
* 根据 mark 查询具体策略并执行,带返回结果
*
* @param mark 策略标识
* @param requestParam 执行策略入参
* @param <REQUEST> 执行策略入参范型
* @param <RESPONSE> 执行策略出参范型
* @return
*/
public <REQUEST, RESPONSE> RESPONSE chooseAndExecuteResp(String mark, REQUEST requestParam) {
AbstractExecuteStrategy executeStrategy = choose(mark);
return (RESPONSE) executeStrategy.executeResp(requestParam);
}
@Override
public void onApplicationEvent(ApplicationInitializingEvent event) {
Map<String, AbstractExecuteStrategy> actual = ApplicationContextHolder.getBeansOfType(AbstractExecuteStrategy.class);
actual.forEach((beanName, bean) -> {
AbstractExecuteStrategy beanExist = abstractExecuteStrategyMap.get(bean.mark());
if (beanExist != null) {
throw new ServiceException(String.format("[%s] Duplicate execution policy", bean.mark()));
}
abstractExecuteStrategyMap.put(bean.mark(), bean);
});
}
}