文章目录
创建design-demo项目
创建OrderController
创建OrderService
创建OrderServiceImpl
创建AbstractAuditLogProcessor
创建AuditLog
创建LoginLogProcessor
创建OrderLogProcessor
创建PayLogProcessor
创建Order
创建OrderState
创建OrderStateChangeAction
创建OrderStateMachineConfig
创建OrderStateListener
创建StrategyFacade
创建AddFuncFactory
创建PayFactory
创建StrategyFactory
创建AddFuncDecorator
创建AbstractAddFuncDecorator
创建StrategyEnum
校验是否正常工作
创建design-demo项目
项目代码:https://gitee.com/java_wxid/java_wxid/tree/master/demo/design-demo
项目结构如下(示例):
创建OrderController
代码如下(示例):
package com.example.designdemo.controller; import com.example.designdemo.order.pojo.Order; import com.example.designdemo.pay.pojo.PayBody; import com.example.designdemo.service.OrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; /** * @Author: zhiwei Liao * @Date: 2022/9/26 21:29 * @Description: 订单管理,这里简单写写,主要是设计模式,别抠细节 */ @RestController public class OrderController { @Autowired private OrderService orderService; @GetMapping("mkOrder") public Order createOrder(@RequestParam Integer oid) { return orderService.createOrder(oid); } @PostMapping("/pay") public Order payOrder(@RequestBody PayBody payBody){ return orderService.pay(payBody); } @GetMapping("/send") public Order send(@RequestParam Integer oid) { return orderService.send(oid); } @GetMapping("/receive") public Order receive(@RequestParam Integer oid) { return orderService.receive(oid); } }
创建OrderService
代码如下(示例):
package com.example.designdemo.service; import com.example.designdemo.order.pojo.Order; import com.example.designdemo.pay.pojo.PayBody; /** * @Author: zhiwei Liao * @Date: 2022/9/25 9:28 * @Description: */ public interface OrderService { Order createOrder(Integer oid); Order pay(PayBody payBody); Order send(Integer oid); Order receive(Integer oid); }
创建OrderServiceImpl
代码如下(示例):
package com.example.designdemo.service.impl;
import com.example.designdemo.order.auditlog.OrderLogProcessor;
import com.example.designdemo.order.auditlog.PayLogProcessor;
import com.example.designdemo.order.pojo.Order;
import com.example.designdemo.order.pojo.OrderState;
import com.example.designdemo.order.pojo.OrderStateChangeAction;
import com.example.designdemo.pay.facade.StrategyFacade;
import com.example.designdemo.pay.pojo.PayBody;
import com.example.designdemo.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
@Author: zhiwei Liao
@Date: 2022/9/26 21:29
@Description:
*/
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private StateMachine<OrderState, OrderStateChangeAction> orderStateMachine;
@Autowired
private StateMachinePersister<OrderState, OrderStateChangeAction, Order> stateMachinePersister;
@Autowired
private PayLogProcessor payLogProcessor;
@Autowired
private OrderLogProcessor orderLogProcessor;
//模拟一个存储
private List orders = new ArrayList<>();
public Order createOrder(Integer oid) {
Order order = new Order();
order.setOrderState(OrderState.ORDER_WAIT_PAY);
order.setOrderId(oid);
// 创建的order是不是得入库啊?如果不入库,下次访问的时候,是不是找不到了啊。
orders.add(order); // 模拟存储到 db
orderLogProcessor.processAuditLog(“acccount”, “createOrder”, oid.toString());
return order;
}
// 将来我们删除或者增加或者修改任何关于付款的模块,无需改动service。
//不会对调用层产生任何代码的改动。
// 调用层使用我们的pay 模块,无需关系实现的逻辑,只需要将入参传给我们的pay模块即可。
public Order pay(PayBody payBody) {
// 书写我们的付款逻辑
boolean flag = false;
flag = StrategyFacade.pay(payBody);
if(flag) {
Order order = (Order) orders.get(0); // 模拟查询db代码
payLogProcessor.processAuditLog(payBody.getAccount(), “pay”, order.getOrderId().toString());
Message message = MessageBuilder
.withPayload(OrderStateChangeAction.PAY_ORDER).setHeader(“order”, order).build();
//发送消息,发送给谁?和状态机有没有关系啊? 有
if(changeStateAction(message,order)) {
return order;
}
//如果是 true,我们要保存到db
saveToDb(payBody);
}
return null;
}
private void saveToDb(PayBody payBody) {
}
public Order send(Integer oid) {
Order order = (Order) orders.get(0); // 模拟查询db代码
Message message = MessageBuilder
.withPayload(OrderStateChangeAction.SEND_ORDER).setHeader(“order”, order).build();
if(changeStateAction(message,order)) {
return order;
}
return null;
}
public Order receive(Integer oid) {
Order order = (Order) orders.get(0); // 模拟查询db代码
Message message = MessageBuilder
.withPayload(OrderStateChangeAction.RECEIVE_ORDER).setHeader(“order”, order).build();
if(changeStateAction(message,order)) {
return order;
}
return null;
}
private boolean changeStateAction(Message message, Order order) {
try {
orderStateMachine.start();
stateMachinePersister.restore(orderStateMachine, order); // 待议
boolean res = orderStateMachine.sendEvent(message);
stateMachinePersister.persist(orderStateMachine, order); // 持久
return res;
} catch (Exception e) {
e.printStackTrace();
} finally {
orderStateMachine.stop();
}
return false;
}
}
创建AbstractAuditLogProcessor
代码如下(示例):
package com.example.designdemo.order.auditlog; import com.example.designdemo.order.auditlog.pojo.AuditLog; import java.util.Date; /** * @Author: zhiwei Liao * @Date: 2022/9/26 21:29 * @Description: */ public abstract class AbstractAuditLogProcessor { // 创建我们的 AuditLog (基础部分) public final AuditLog buildAuditLog(String account, String action, String orderId){ AuditLog auditLog = new AuditLog(); auditLog.setAccount(account); auditLog.setAction(action); auditLog.setOrderId(orderId); auditLog.setDate(new Date()); return auditLog; } protected abstract AuditLog buildDetails(AuditLog auditLog); public final void sendToQueue(AuditLog auditLog) { //send toQueue(auditLog) } public final void processAuditLog(String account, String action, String orderId) { this.sendToQueue(buildDetails(buildAuditLog(account, action, orderId))); } }
创建AuditLog
代码如下(示例):
package com.example.designdemo.order.auditlog.pojo;
import java.util.Date;
/**
@Author: zhiwei Liao
@Date: 2022/9/26 21:29
@Description:
*/
public class AuditLog {
private String account;
private String action;
private Date date;
private String orderId;
private Object details; //订单创建需要有相关产品信息;
// 订单支付需要有相关产品信息以及支付方式和支付金额。
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public Object getDetails() {
return details;
}
public void setDetails(Object details) {
this.details = details;
}
@Override
public String toString() {
return “AuditLog{” +
“account='” + account + ‘’’ +
“, action='” + action + ‘’’ +
“, date=” + date +
“, orderId='” + orderId + ‘’’ +
“, details=” + details +
‘}’;
}
}
创建LoginLogProcessor
代码如下(示例):
package com.example.designdemo.order.auditlog; import com.example.designdemo.order.auditlog.pojo.AuditLog; import org.springframework.stereotype.Component; /** * @Author: zhiwei Liao * @Date: 2022/9/26 21:29 * @Description: */ @Component public class LoginLogProcessor extends AbstractAuditLogProcessor{ @Override protected AuditLog buildDetails(AuditLog auditLog) { return auditLog; } }
创建OrderLogProcessor
代码如下(示例):
package com.example.designdemo.order.auditlog; import com.example.designdemo.order.auditlog.pojo.AuditLog; import org.springframework.stereotype.Component; /** * @Author: zhiwei Liao * @Date: 2022/9/26 21:29 * @Description: */ @Component public class OrderLogProcessor extends AbstractAuditLogProcessor{ @Override protected AuditLog buildDetails(AuditLog auditLog) { String orderId = auditLog.getOrderId(); String productDetails = "通过 orderId 获取"; auditLog.setDetails(productDetails); System.out.println(auditLog); return auditLog; } }
创建PayLogProcessor
代码如下(示例):
package com.example.designdemo.order.auditlog; import com.example.designdemo.order.auditlog.pojo.AuditLog; import org.springframework.stereotype.Component; /** * @Author: zhiwei Liao * @Date: 2022/9/26 21:29 * @Description: */ @Component public class PayLogProcessor extends AbstractAuditLogProcessor{ @Override protected AuditLog buildDetails(AuditLog auditLog) { String orderId = auditLog.getOrderId(); String allDetails = "通过 orderId 或者是参数 获取产品信息,金额,支付方式"; auditLog.setDetails(allDetails); System.out.println(auditLog); return auditLog; } }
创建Order
代码如下(示例):
package com.example.designdemo.order.pojo; /** * @Author: zhiwei Liao * @Date: 2022/9/26 21:29 * @Description:状态转化的一个控制机。状态机:初始化状态;配置我们的所有状态之间的转化关系;一些持久化的工作(redis)。 */ public class Order { private Integer orderId; private OrderState orderState;//订单状态 public Integer getOrderId() { return orderId; } public void setOrderId(Integer orderId) { this.orderId = orderId; } public OrderState getOrderState() { return orderState; } public void setOrderState(OrderState orderState) { this.orderState = orderState; } }
创建OrderState
代码如下(示例):
package com.example.designdemo.order.pojo; /** * @Author: zhiwei Liao * @Date: 2022/9/26 21:29 * @Description:订单状态 */ public enum OrderState { ORDER_WAIT_PAY, // 待支付 ORDER_WAIT_SEND, // 待发货 ORDER_WAIT_RECEIVE, // 待收货 ORDER_FINISH; // 完成订单 }
创建OrderStateChangeAction
代码如下(示例):
package com.example.designdemo.order.pojo; /** * @Author: zhiwei Liao * @Date: 2022/9/26 21:29 * @Description:订单状态操作 */ public enum OrderStateChangeAction { PAY_ORDER, // 支付操作 SEND_ORDER, // 发货操作 RECEIVE_ORDER; // 收货操作 }
创建OrderStateMachineConfig
代码如下(示例):
package com.example.designdemo.order.config; import com.example.designdemo.order.pojo.Order; import com.example.designdemo.order.pojo.OrderState; import com.example.designdemo.order.pojo.OrderStateChangeAction; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.statemachine.StateMachineContext; import org.springframework.statemachine.StateMachinePersist; import org.springframework.statemachine.config.EnableStateMachine; import org.springframework.statemachine.config.StateMachineConfigurerAdapter; import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; import org.springframework.statemachine.persist.DefaultStateMachinePersister; import org.springframework.statemachine.support.DefaultStateMachineContext; import java.util.EnumSet; /** * @Author: zhiwei Liao * @Date: 2022/9/26 21:29 * @Description: */ @Configuration @EnableStateMachine(name="orderStateMachine") public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderState, OrderStateChangeAction> { public void configure(StateMachineStateConfigurer<OrderState, OrderStateChangeAction> states) throws Exception { states.withStates().initial(OrderState.ORDER_WAIT_PAY) .states(EnumSet.allOf(OrderState.class)); } public void configure(StateMachineTransitionConfigurer<OrderState, OrderStateChangeAction> transitions) throws Exception { transitions.withExternal().source(OrderState.ORDER_WAIT_PAY) .target(OrderState.ORDER_WAIT_SEND) .event(OrderStateChangeAction.PAY_ORDER) .and() .withExternal().source(OrderState.ORDER_WAIT_SEND) .target(OrderState.ORDER_WAIT_RECEIVE) .event(OrderStateChangeAction.SEND_ORDER) .and() .withExternal().source(OrderState.ORDER_WAIT_RECEIVE) .target(OrderState.ORDER_FINISH) .event(OrderStateChangeAction.RECEIVE_ORDER); } // 配置状态机持久化 @Bean public DefaultStateMachinePersister machinePersister() { return new DefaultStateMachinePersister<>(new StateMachinePersist<Object, Object, Order>() { @Override public void write(StateMachineContext<Object, Object> stateMachineContext, Order order) throws Exception { //持久化操作。可以通过任何形式进行持久化。redis 、 mongodb、mysql,ecache } @Override public StateMachineContext<Object, Object> read(Order order) throws Exception { // 本来是应该从持久化组件里进行读取的。但是没做持久化 return new DefaultStateMachineContext(order.getOrderState(), null, null, null); } }); } }
创建OrderStateListener
代码如下(示例):
package com.example.designdemo.order.listener; import com.example.designdemo.order.pojo.Order; import com.example.designdemo.order.pojo.OrderState; import com.example.designdemo.order.pojo.OrderStateChangeAction; import org.springframework.messaging.Message; import org.springframework.statemachine.annotation.OnTransition; import org.springframework.statemachine.annotation.WithStateMachine; import org.springframework.stereotype.Component; /** * @Author: zhiwei Liao * @Date: 2022/9/26 21:29 * @Description:监听器是监听到 action 后进行状态的一个变更。 */ @Component("orderStateListener") @WithStateMachine(name="orderStateMachine") public class OrderStateListener { @OnTransition(source = "ORDER_WAIT_PAY", target = "ORDER_WAIT_SEND") public boolean payToSend(Message<OrderStateChangeAction> message){ Order order = (Order) message.getHeaders().get("order"); order.setOrderState(OrderState.ORDER_WAIT_SEND); return true; } @OnTransition(source = "ORDER_WAIT_SEND", target = "ORDER_WAIT_RECEIVE") public boolean sendToReceive(Message<OrderStateChangeAction> message){ Order order = (Order) message.getHeaders().get("order"); order.setOrderState(OrderState.ORDER_WAIT_RECEIVE); return true; } @OnTransition(source = "ORDER_WAIT_RECEIVE", target = "ORDER_FINISH") public boolean receiveToFinish(Message<OrderStateChangeAction> message){ Order order = (Order) message.getHeaders().get("order"); order.setOrderState(OrderState.ORDER_FINISH); return true; } }
创建StrategyFacade
代码如下(示例):
package com.example.designdemo.pay.facade; import com.example.designdemo.pay.additionalDecorator.AddFuncDecorator; import com.example.designdemo.pay.context.PayContext; import com.example.designdemo.pay.factory.AddFuncFactory; import com.example.designdemo.pay.factory.PayFactory; import com.example.designdemo.pay.strategy.PayStrategy; import com.example.designdemo.pay.factory.StrategyFactory; import com.example.designdemo.pay.pojo.PayBody; import com.example.designdemo.pay.strategyEnum.StrategyEnum; /** * @Author: zhiwei Liao * @Date: 2022/9/25 11:27 * @Description: 门面模式,最终只暴露门面即可,门面就是我们的超级封装 */ public class StrategyFacade { // 定义一个map,将对应关系提前初始化好。 // 双十一的时候,有大量的用户进行下单(千万级),就会造成千万级的pay接口的调用。 // 很可惜,这部分代码里边有两个 new 关键字(new PayContext(payStrategy) 和 new AddFuncDecorator)。 // 如果瞬时见。有几十万的并发进来,那么会创建几十万个 context对象和 addFunc对象,造成 年轻代的eden区的频繁对象创建 // 虽然说调用完就进行了对象的垃圾收集,但是这么多的访问对象进来会造成,minorgc。 // 1. 单例模式吗?PayContext创建是基于payStrategy,不止一种paycontext啊,用单例不行呀。 AddFuncDecorator 是基于PayContext // 创建的,PayContext 不止一种,AddFuncDecorator 也不止一种。 // 2. 享元模式。享元模式是单例模式的一种思想升级。单例模式,针对的是同一种对象,没有任何不同的细节。而享元模式,针对多个对象。 // 多个对象:同一种class,但是里边的属性有些许不同。PayContext是同一种对象吧?是的; PayContext 是不是有细节上的不同呢?是的, // payStrategy不同; 那么我们是否可以知道这个PayContext的种类数量呢?是的,目前有三种。 享元模式能够对这可控数量的有不同细节的 //同一种class对象进行共享,保证我们的程序不频繁的创建对象。 public static Boolean pay(PayBody payBody) { //获取我们的 策略枚举 StrategyEnum strategyEnum = getStrategyEnum(payBody.getType()); if(strategyEnum == null) { return false; } //获取我们的策略对象 PayStrategy payStrategy = StrategyFactory.getPayStrategy(strategyEnum); //生成我们的策略上下文 PayContext context = PayFactory.getPayContext(payStrategy); // 享元模式解决高并发下频繁创建对象的问题 // 装饰一下 context,。立马多了一个功能 // 我看这行代码啊,就不顺眼。代理模式搞他。 AddFuncDecorator addFuncDecorator = (AddFuncDecorator) AddFuncFactory.getAddFunc(context); // 享元模式解决高并发下频繁创建对象的问题 //进行扣款 return addFuncDecorator.execute(payBody); } private static StrategyEnum getStrategyEnum(int type) { switch (type) { case 0: return StrategyEnum.ZfbPayStrategy; case 1: return StrategyEnum.WxPayStrategy; case 2: return StrategyEnum.BankPayStrategy; default: return null; } } }
创建AddFuncFactory
代码如下(示例):
package com.example.designdemo.pay.factory; import com.example.designdemo.pay.additionalDecorator.AbstractAddFuncDecorator; import com.example.designdemo.pay.additionalDecorator.AddFuncDecorator; import com.example.designdemo.pay.context.PayContext; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @Author: zhiwei Liao * @Date: 2022/9/25 20:53 * @Description: */ public class AddFuncFactory { // 工厂的目的是生产 AddFuncDecorator; 生产几个啊? 多个:享元 // key 应该是能够和 AbstractAddFuncDecorator 做成对应的东西。 // 这个map最多保存是三个对象。 public final static Map<PayContext, AbstractAddFuncDecorator> maps = new ConcurrentHashMap<>(); public static AbstractAddFuncDecorator getAddFunc(PayContext payContext) { if(maps.get(payContext) == null) { AddFuncDecorator addFuncDecorator = new AddFuncDecorator(payContext); maps.put(payContext, addFuncDecorator); } return maps.get(payContext); } }
创建PayFactory
代码如下(示例):
package com.example.designdemo.pay.factory; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import com.example.designdemo.pay.context.PayContext; import com.example.designdemo.pay.strategy.PayStrategy; /** * @author zhiweiLiao<zhiwei.liao @ sgs.com> * @Description 享元模式解决高并发下频繁创建对象的问题 * @Date create in 2022/9/28 0028 13:57 */ public class PayFactory { public final static Map<PayStrategy, PayContext> maps = new ConcurrentHashMap<>(); public static PayContext getPayContext(PayStrategy payStrategy) { if(maps.get(payStrategy) == null) { PayContext payContext = new PayContext(payStrategy); maps.put(payStrategy, payContext); } return maps.get(payStrategy); } }
创建StrategyFactory
代码如下(示例):
package com.example.designdemo.pay.factory; import com.example.designdemo.pay.strategy.PayStrategy; import com.example.designdemo.pay.strategyEnum.StrategyEnum; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @Author: zhiwei Liao * @Date: 2022/9/25 10:53 * @Description: 策略工厂 工厂类依靠策略枚举返回策略类 后面都不需要修改了,因为它是一个无状态的 使用饿汉单例模式创建 */ public class StrategyFactory { private static final Map<String, PayStrategy> strategyMaps = new ConcurrentHashMap(); public static PayStrategy getPayStrategy(StrategyEnum strategyEnum){ PayStrategy payStrategy = strategyMaps.get(strategyEnum.getValue()); try { payStrategy = (PayStrategy) Class.forName(strategyEnum.getValue()).newInstance(); strategyMaps.put(strategyEnum.getValue(), payStrategy); } catch (Exception e) { //异常信息打印 } return payStrategy; } }
创建AddFuncDecorator
代码如下(示例):
package com.example.designdemo.pay.additionalDecorator; import com.example.designdemo.pay.context.AbstractPayContext; import com.example.designdemo.pay.pojo.PayBody; /** * @Author: zhiwei Liao * @Date: 2022/9/25 20:53 * @Description:abstractPayContext 不是共享的,因为有的小伙伴选择 zfb 支付,有的小伙伴选择wx支付,等等。。。 */ public class AddFuncDecorator extends AbstractAddFuncDecorator{ public AddFuncDecorator(AbstractPayContext abstractPayContext) { super(abstractPayContext); } // 新活儿 @Override public void additionalFunction(PayBody payBody) { // 共享的,跟支付策略没有任何关系 String product = payBody.getProduct(); // 从db里边获取 product的详细信息。 // 从配置中心(redis缓存)里获取产品的更新策略。 // 根据策略更新用户平台币 或(和) 发放红包。 System.out.println("更新平台币成功,发送红包到用户优惠券模块成功。"); } @Override public Boolean execute(PayBody payBody) { // 算共享的。共享的调用逻辑 Boolean result = super.execute(payBody); //老活儿 this.additionalFunction(payBody); // 新活儿. 新活儿的各种重试,失败补偿 return result; } }
创建AbstractAddFuncDecorator
代码如下(示例):
package com.example.designdemo.pay.additionalDecorator; import com.example.designdemo.pay.context.AbstractPayContext; import com.example.designdemo.pay.pojo.PayBody; /** * @Author: zhiwei Liao * @Date: 2022/9/25 20:53 * @Description: */ public abstract class AbstractAddFuncDecorator extends AbstractPayContext { // 这是我们的装饰器类。专门干装修的。 专门添加新功能的(平台币,红包) // 装饰的是谁啊? 我作为一个称职的装饰器,我必须得知道装饰的是谁,不然我咋干活儿啊。 private AbstractPayContext abstractPayContext = null; public AbstractAddFuncDecorator(AbstractPayContext abstractPayContext) { this.abstractPayContext = abstractPayContext; } // 开始干活儿 //1. 老活儿。 支付。但是我又不能修改支付代码,也不能修改支付逻辑。 @Override public Boolean execute(PayBody payBody) { return abstractPayContext.execute(payBody); } //2. 老活儿不合适,没你装饰器照样能execute。 新活儿:平台币,红包) public abstract void additionalFunction(PayBody payBody); }
创建StrategyEnum
代码如下(示例):
package com.example.designdemo.pay.strategyEnum; /** * @Author: zhiwei Liao * @Date: 2022/9/25 10:56 * @Description: 准备使用反射 */ public enum StrategyEnum { ZfbPayStrategy("com.example.designdemo.pay.strategy.ZfbPayStrategy"), WxPayStrategy("com.example.designdemo.pay.strategy.WxPayStrategy"), BankPayStrategy("com.example.designdemo.pay.strategy.BankPayStrategy"); String value = ""; StrategyEnum(String value){ this.value = value; } public String getValue(){ return this.value; } }
校验是否正常工作