1. 基于组合模式与访问者模式完成权限删除功能
适合用于复杂数据结构的操作,如树形结构的查找,删除等
类图
代码编写
访问者模式:设计一个访问节点类(Priority),一个操作行为的接口类(PriorityOperation,有多种实现),在节点类里面提供一个方法,接收一个接口类,并且调用接口类的方法,把节点类传进去.这样只要new一个节点类,执行节点类的方法,同时传入一个操作接口实现类,就可以执行不同的操作逻辑
Priority :节点类,同时有一个执行方法,需要传入一个PriorityOperation接口,这个类在执行的时候可以把自己也传进去
PriorityOperation:具体的逻辑接口类,根据逻辑的不同,可以有多个实现类,执行类通过递归调用Priority 方法
组合模式:是一种数据结构的设计,比如树形结构,把一组相似的对象当作一个单一的对象,用一个类来代替一个复杂的数据结构,比如下面这段代码(可能会涉及到递归调用)
public class Priority extends AbstractObject {
//子权限节点
private List<Priority> children = new ArrayList<Priority>();
}
/** 调用入口service类
* 删除权限分成两步:
* 1.查询权限是否是否被角色或者账号给关联着,关联则不能删除
* 2.删除权限
*/
@Override
public Boolean removePriority(Long id) throws Exception {
// 根据id查询权限
Priority priority = priorityDAO.getPriorityById(id)
.clone(Priority.class);
// 检查这个权限以及其下任何一个子权限,是否被角色或者账号给关联着
RelatedCheckPriorityOperation relatedCheckOperation = context.getBean(
RelatedCheckPriorityOperation.class);
Boolean relateCheckResult = priority.execute(relatedCheckOperation);
if(relateCheckResult) {
return false;
}
// 递归删除当前权限以及其下所有的子权限
RemovePriorityOperation removeOperation = context.getBean(
RemovePriorityOperation.class);
priority.execute(removeOperation);
return true;
}
/** Priority 访问接口
* 接收一个权限树操作接口
* @param visitor 权限树访问者
*/
public <T> T execute(PriorityOperation<T> operation) throws Exception {
return operation.doExecute(this);
}
/**
* 权限操作接口
*/
public interface PriorityOperation<T> {
/**
* 执行这个操作
* @param priority 权限
* @return 处理结果
* @throws Exception
*/
T doExecute(Priority priority) throws Exception;
}
/** PriorityOperation的实现类
* 检查权限是否被关联的操作
*/
@Component
@Scope("prototype")
public class RelatedCheckPriorityOperation implements PriorityOperation<Boolean> {
/**
* 访问权限树节点
*/
@Override
public Boolean doExecute(Priority node) throws Exception {
List<PriorityDO> priorityDOs = priorityDAO
.listChildPriorities(node.getId());
if(priorityDOs != null && priorityDOs.size() > 0) {
for(PriorityDO priorityDO : priorityDOs) {
Priority priorityNode = priorityDO.clone(Priority.class);
//递归调用方法,如果是最后叶子节点,则不会进入里面
priorityNode.execute(this);
}
}
if(relateCheck(node)) {
this.relateCheckResult = true;
}
return this.relateCheckResult;
}
}
2. 结合模板方法模式、命令模式、工厂方法模式开发库存管理功能
类图
代码编写
命令模式:一接口多实现, 把一个一个的行为封装成一个具体的类,实现同一接口,比如取消订单,支付订单行为的逻辑都写在各自的类里面,外界调用的时候,可以在需要的地方获取一个具体的命令实现类,执行实现类方法就行.
StockUpdater:命令执行接口(一接口),工厂类可以根据参数返回不同的实现类.
AbstractStockUpdater:命令执行的抽象模板类,继承接口类,定义了执行步骤的抽象方法和公共方法,步骤的具体实现交给实现类
PurchaseInputStockUpdater:具体的执行实现类(多实现),继承了AbstractStockUpdater
StockUpdaterFactory:命令工厂(也可以改成只有一个工厂,通过传入一个参数,返回不同的StockUpdater实现类),工厂的目的就是统一的创建命令类
AbstractStockUpdaterFactory:命令抽象工厂,抽取每个实现类的公共方法
PurchaseInputStockUpdaterFactory:具体的工厂实现类,每个命令对应一个工厂
service方法入口
/**
* 采购入库库存更新命令工厂
*/
@Autowired
private PurchaseInputStockUpdaterFactory<PurchaseInputOrderDTO> purchaseInputStockUpdateCommandFactory;
@Override
public Boolean informPurchaseInputFinished(PurchaseInputOrderDTO purchaseInputOrderDTO){
try {
//根据不同的业务逻辑,使用不同的工厂创建命令
StockUpdater goodsStockUpdateCommand =
purchaseInputStockUpdateCommandFactory.create(purchaseInputOrderDTO);
//调用具体的命令实现逻辑
goodsStockUpdateCommand.updateGoodsStock();
} catch (Exception e) {
logger.error("error", e);
return false;
}
return true;
}
// PurchaseInputStockUpdaterFactory 具体的实现工厂
public class PurchaseInputStockUpdaterFactory<T> extends AbstractStockUpdaterFactory<T> {
@Override
protected StockUpdater create(T paramter, List<GoodsStockDO> goodsStockDOs) {
PurchaseInputOrderDTO purchaseInputOrderDTO=(PurchaseInputOrderDTO)paramter;
List<PurchaseInputOrderItemDTO> purchaseInputOrderItemDTOS=purchaseInputOrderDTO.getItems();
Map<Long,PurchaseInputOrderItemDTO> purchaseInputOrderItemDTOMap=
new HashMap<Long, PurchaseInputOrderItemDTO>(CollectionSize.DEFAULT);
if(purchaseInputOrderItemDTOS!=null && purchaseInputOrderItemDTOS.size()>0){
for(PurchaseInputOrderItemDTO purchaseInputOrderItemDTO:purchaseInputOrderItemDTOS){
purchaseInputOrderItemDTOMap.put(purchaseInputOrderItemDTO.getGoodsSkuId(),purchaseInputOrderItemDTO);
}
}
return new PurchaseInputStockUpdater(goodsStockDOs,goodsStockDAO,dateProvider,purchaseInputOrderItemDTOMap);
}
}
/**
* 商品库存更新命令的抽象基类
*/
public abstract class AbstractStockUpdater implements StockUpdater {
private static final Logger logger = LoggerFactory.getLogger(
AbstractStockUpdater.class);
//实现接口够方法,在里面定义执行步骤
@Override
public Boolean updateGoodsStock() {
try{
//抽象方法,给子类实现
updateSaleStockQuantity();
updateLockedStockQuantity();
updateSaledStockQuantity();
//公共方法,自己实现
updateStockStatus();
executeUpdateGoodsStock();
}catch (Exception e){
logger.error("error",e);
}
return true;
}
/**
* 更新销售库存
*/
protected abstract void updateSaleStockQuantity();
/**
* 更新锁定库存
*/
protected abstract void updateLockedStockQuantity();
/**
* 更新已销售库存
*/
protected abstract void updateSaledStockQuantity();
/**
* 更新库存状态
*/
private void updateStockStatus(){
for(GoodsStockDO goodsStockDO:goodsStockDOList){
if(goodsStockDO.getSaleStockQuantity()>0L){
goodsStockDO.setStockStatus(StockStatus.IN_STOCK);
}else {
goodsStockDO.setStockStatus(StockStatus.NOT_IN_STOCK);
}
}
}
/**
* 执行更新库存操作
*/
private void executeUpdateGoodsStock() throws Exception {
for(GoodsStockDO goodsStockDO:goodsStockDOList){
goodsStockDAO.updateGoodsStock(goodsStockDO);
}
}
}
// 具体的命令实现类
public class PurchaseInputStockUpdater extends AbstractStockUpdater {
public PurchaseInputStockUpdater(List<GoodsStockDO> goodsStockDOList,
GoodsStockDAO goodsStockDAO,
DateProvider dateProvider,
Map<Long, PurchaseInputOrderItemDTO> purcahseInputOrderItemDTOMap) {
super(goodsStockDOList, goodsStockDAO, dateProvider);
this.purcahseInputOrderItemDTOMap=purcahseInputOrderItemDTOMap;
}
@Override
protected void updateSaleStockQuantity() {
//具体业务逻辑
for(GoodsStockDO goodsStockDO:goodsStockDOList){
PurchaseInputOrderItemDTO purchaseInputOrderItemDTO=
purcahseInputOrderItemDTOMap.get(goodsStockDO.getGoodsSkuId());
goodsStockDO.setSaleStockQuantity(goodsStockDO.getSaleStockQuantity()
+purchaseInputOrderItemDTO.getArrivalCount());
}
}
@Override
protected void updateLockedStockQuantity() {
//具体业务逻辑
}
@Override
protected void updateSaledStockQuantity() {
//具体业务逻辑
}
}
3.基于中介者模式和观察者模式实现异步通知调度中心更新库存
类图
代码编写
观察者模式:当一个对象被修改时,则会自动通知依赖它的对象
StockUpdateQueue:消息内存队列,所谓的中介者,最终目的就是解耦,通过消息队列进行解耦
StockUpdateResultManager:商品库存更新结果管理组件接口,定义了设置观察目标,通知观察目标发生变化和获取观察目标的方法
StockUpdateObservable:观察目标,发送变化,会通知观察者
StockUpdateObserver:观察者,通过监听观察目标,目标发送变化执行相应逻辑
service方法入口
/**
* 通知库存中心,“提交订单”事件发生了
* @param orderDTO 订单DTO
* @return 处理结果
*/
@Override
public Boolean informSubmitOrderEvent(OrderInfoDTO orderDTO) {
try {
//命令+抽象工厂模式
StockUpdater goodsStockUpdateCommand =submitOrderStockUpdaterFactory.create(orderDTO);
goodsStockUpdateCommand.updateGoodsStock();
//提交订单发送消息
StockUpdateMessage stockUpdateMessage=new StockUpdateMessage();
stockUpdateMessage.setId(UUID.randomUUID().toString().replace("-", ""));
stockUpdateMessage.setOperation(GoodsStockUpdateOperation.SUBMIT_ORDER);
stockUpdateMessage.setParameter(orderDTO);
stockUpdateQueue.put(stockUpdateMessage);
// 监听异步处理结果
stockUpdateResultManager.observe(stockUpdateMessage.getId());
} catch (Exception e) {
logger.error("error", e);
return false;
}
return true;
}
/**
* 商品库存更新消息的队列接口,实现类也只是把消息放入ArrayBlockingQueue<StockUpdateMessage> queue 就不贴出来了
*/
public interface StockUpdateQueue {
// 将一个消息放入队列
void put(StockUpdateMessage message) throws Exception;
// 从队列中取出一个消息
StockUpdateMessage take() throws Exception;
}
@Component
public class StockUpdateResultManagerImpl implements StockUpdateResultManager {
//观察目标map
private Map<String,StockUpdateObservable> stockUpdateObservableMap=new ConcurrentHashMap<String, StockUpdateObservable>();
//观察者
@Autowired
private StockUpdateObserver observer;
// 设置对商品库存更新结果的观察,消息的生产者执行的方法
@Override
public void observe(String messageId) {
//新建一个观察目标,并且把他和观察者关联起来
StockUpdateObservable stockUpdateObservable=new StockUpdateObservable(messageId);
stockUpdateObservable.addObserver(observer);
stockUpdateObservableMap.put(messageId,stockUpdateObservable);
}
// 获取商品库存更新结果的观察目标,消息的消费者执行的方法
@Override
public void inform(String messageId, Boolean result) {
//获取观察目标,并设置目标发生变化
StockUpdateObservable stockUpdateObservable=stockUpdateObservableMap.get(messageId);
stockUpdateObservable.setResult(result);
stockUpdateObservableMap.remove(messageId);
}
// 获取库存更新结果观察目标
@Override
public StockUpdateObservable getObservable(String messageId) {
return stockUpdateObservableMap.get(messageId);
}
}
// 观察目标
public class StockUpdateObservable extends Observable {
private String messageId; //消息id
//设置消息结果,并且通知观察者发送变化
public void setResult(Boolean result){
StockUpdateResult stockUpdateResult=new StockUpdateResult();
stockUpdateResult.setResult(result);
stockUpdateResult.setMessageId(messageId);
//通知观察者目标发送了变化
this.setChanged();
this.notifyObservers(stockUpdateResult);
}
}
//观察者
@Component
public class StockUpdateObserver implements Observer {
//观察目标发生变化,会执行update方法
@Override
public void update(Observable o, Object arg) {
StockUpdateResult stockUpdateResult=(StockUpdateResult)arg;
logger.info("商品库存更新消息[messageId=" + stockUpdateResult.getMessageId() + "]"
+ "的异步处理结果为:" + stockUpdateResult.getResult());
}
}
4. 原型模式完善深度克隆功能
DTO->VO 把DTO克隆为VO
dto.clone(vo,diretion)
1.调用浅克隆,完成基础属性克隆
2. 判断是否dto里面的属性是否有list,通过反射获取属性
3.拿到list集合数据
4.拿到list集合的泛型,并且转换为目标的泛型(获取原来的泛型名称,最后几个字符改成目标的字符)
5. 遍历list集合
for(
对集合里面的数据进行递归克隆,集合里面对象如果还有list的话,也进行深度克隆,拿到克隆list
)
6.拿到list的set方法,把克隆的list集合放进去
/**
* 深度克隆 字段名字要一样
* @param clazz
* @param direction
* @return
* @throws Exception
*/
public <T> T clone(Class<T> clazz,Integer cloneDirection)throws Exception {
//DTO->VO
//dto.clone(vo,diretion)
//1.调用浅克隆,完成基础属性克隆
T targetClass=clazz.newInstance();
BeanCopierUtils.copyProperties(this,targetClass);
//2. 拿到所有属性,判断是否dto里面的属性是否有list
Field[] fields=this.getClass().getDeclaredFields();
for(Field field:fields){
field.setAccessible(true);
//field.getType() 拿到List 不是 List<Relation>
if(field.getType()!= List.class){
continue;
}
//3.拿到list集合数据
List<?> list=(List<?>)field.get(this);
if(list == null || list.size() == 0) {
continue;
}
//4.1拿到list集合的泛型
//RelationDTO
Class<?> listGenericClazz = getListGenericType(field);
//4.2 转换为目标的泛型
//此时获取到的就是RelationVO
Class<?> cloneTargetClazz = getCloneTargetClazz(listGenericClazz, cloneDirection);
List<AbstractObject> clonedList=new ArrayList<AbstractObject>();
//5. 遍历list集合
// 对集合里面的数据进行递归克隆,拿到克隆list
cloneList(list, clonedList, cloneTargetClazz, cloneDirection);
//6.拿到list的set方法,把克隆的list集合放进去
// 获取设置克隆好的list的方法名称(根据字段名字获取,所以名字要一样才行)
// setRelations
Method setFieldMethod = getSetCloneListFieldMethodName(field, clazz);
setFieldMethod.invoke(targetClass,clonedList);
}
return targetClass;
}
// 将一个list克隆到另外一个list
private void cloneList(List<?> targetList, List<AbstractObject> clonedList,
Class<?> cloneTargetClazz, Integer cloneDirection) throws Exception {
for(Object object:targetList){
AbstractObject obj=(AbstractObject)object;
// 将集合中的RelationDTO,调用其clone()方法,将其往RelationVO去克隆
AbstractObject clonObjec=(AbstractObject)obj.clone(cloneTargetClazz,cloneDirection);
// RelationVO的集合
clonedList.add(clonObjec);
}
}
5.基于策略模式与抽象工厂模式完成订单价格计算功能
类图
代码编写
策略模式:也是一接口多实现,主要替换一堆的if…else,对同一对象的判断,需要执行不同的行为,比如对促销对象的判断,不同的促销,要执行不同折扣的逻辑,主要就可以传入一个促销对象,判断值不同,执行不同实现类的方法.
跟命令模式不同的是,命令模式可以根据需要执行单个或者多个命令,不会暴露所有的命令,策略模式要提供所有的策略,根据对象判断采用不同的策略,一般执行一种策略
订单计算步骤:
1.计算商品总价格
2.计算运费价格
3.计算促销价格
4.商品总价格+运费价格-促销价格
TotalPriceCalculator: 1种策略->商品总价格:1种实现,金额*数量
FreightCalculator :2种策略->运费价格:2种实现:1.包含赠品的运费实现;2.没有赠品的运费实现
PromotionActivityCalculator 6种策略->促销价格:5种实现+1种默认(没有促销):满减,满赠,单品,多买,赠品,没有促销
OrderPriceCalculatorFactory :负责对上面步骤和9种策略进行组合,根据促销活动,返回各个步骤对应的一个计算组件
上述的9种价格策略,再分成3种价格组合:(工厂)
没有促销的订单组合:商品总价格+运费价格(没有赠品)+促销价格(没有促销)
减金额的促销订单组合:商品总价格+运费价格(没有赠品)+促销价格(满减,单品,多买)
送赠品的促销订单组合:商品总价格+运费价格(包含赠品)+促销价格(满赠,赠品)
service入口
@Override
public OrderInfoDTO calculateOrderPrice(OrderInfoDTO order) throws Exception {
// 定义订单的各种价格
Double totalAmount = 0.0;
Double discountAmount = 0.0;
Double freight = 0.0;
List<OrderItemDTO> giftOrderItems = new ArrayList<OrderItemDTO>();
List<OrderItemDTO> orderItemDTOS= order.getOrderItems();
for(OrderItemDTO item: orderItemDTOS){
// 查询订单条目使用的促销活动
PromotionActivityDTO promotionActivityDTO=promotionService.getById(item.getPromotionActivityId());
// 根据促销活动获取到订单计算组件的工厂,各个工厂里面包含不同计算组件
OrderPriceCalculatorFactory orderPriceCalculatorFactory=
getOrderPriceCalculatorFactory(promotionActivityDTO);
// 获取订单总价的价格计算组件,并计算总价
TotalPriceCalculator totalPriceCalculator=
orderPriceCalculatorFactory.createTotalPriceCalculator();
totalAmount += totalPriceCalculator.calculate(item);
// 获取促销活动的价格计算组件,并计算折扣和赠品
PromotionActivityCalculator promotionActivityCalculator = orderPriceCalculatorFactory
.createPromotionActivityCalculator(promotionActivityDTO);
PromotionActivityResult result=promotionActivityCalculator.calculate(item,promotionActivityDTO);
discountAmount += result.getDiscountAmount();
giftOrderItems.addAll(result.getOrderItems());
// 获取订单运费活动的价格计算组件,并计算运费
FreightCalculator freightCalculator=orderPriceCalculatorFactory.createFreightCalculator();
freight += freightCalculator.calculate(order,item,result);
}
// 给订单设置计算后的结果(同时已经包含了所有的赠品)
order.setTotalAmount(totalAmount);
order.setFreight(freight);
order.setDiscountAmount(discountAmount);
order.setPayableAmount(totalAmount + freight - discountAmount);
order.getOrderItems().addAll(giftOrderItems);
return order;
}
/**
* 获取一个订单价格计算工厂
* @param promotionActivityType 促销活动类型
* @return 订单价格计算工厂
*/
private OrderPriceCalculatorFactory getOrderPriceCalculatorFactory(
PromotionActivityDTO promotionActivity) {
if(promotionActivity == null) {
return defaultOrderPriceCalculatorFactory;
}
Integer promotionActivityType = promotionActivity.getType();
if(PromotionActivityType.DIRECT_DISCOUNT.equals(promotionActivityType)
|| PromotionActivityType.MULTI_DISCOUNT.equals(promotionActivityType)
|| PromotionActivityType.REACH_DISCOUNT.equals(promotionActivityType)) {
return discountOrderPriceCalculatorFactory;
} else {
return giftOrderPriceCalculatorFactory;
}
}
@Component
public class DiscountOrderPriceCalculatorFactory implements OrderPriceCalculatorFactory{
//默认的总金额计算组件
@Autowired
DefaultTotalPriceCalculator defaultTotalPriceCalculator;
//默认的运费计算组件
@Autowired
DefaultFreightCalculator defaultFreightCalculator;
//没有促销活动的计算组件
@Autowired
DefaultPromotionActivityCalculator defaultPromotionActivityCalculator;
//满减类型的促销活动计算组件
@Autowired
private ReachDiscountPromotionActivityCalculator reachDiscountPromotionActivityCalculator;
//多买优惠型的促销活动计算组件
@Autowired
private MultiDiscountPromotionActivityCalculator multiDiscountPromotionActivityCalculator;
//单品促销型的促销活动计算组件
@Autowired
private DirectDiscountPromotionActivityCalcualtor directDiscountPromotionActivityCalcualtor;
@Override
public TotalPriceCalculator createTotalPriceCalculator() {
return defaultTotalPriceCalculator; //商品总价就只有一种
}
@Override
public PromotionActivityCalculator createPromotionActivityCalculator(PromotionActivityDTO promotionActivity) {
// 折扣类型的有3种价格策略,满减,单品,多买
if(promotionActivity==null){
return defaultPromotionActivityCalculator;
}
Integer promotionActivityType=promotionActivity.getType();
if(PromotionActivityType.DIRECT_DISCOUNT.equals(promotionActivityType)){
return directDiscountPromotionActivityCalcualtor;
}else if(PromotionActivityType.MULTI_DISCOUNT.equals(promotionActivityType)){
return multiDiscountPromotionActivityCalculator;
}else if(PromotionActivityType.REACH_DISCOUNT.equals(promotionActivityType)){
return reachDiscountPromotionActivityCalculator;
}
return defaultPromotionActivityCalculator;
}
@Override
public FreightCalculator createFreightCalculator() {
return defaultFreightCalculator; //折扣类型的对应运费计算类型
}
}
6.基于状态模式完成商品管理模块的状态流转逻辑封装
类图
代码编写
状态模式:行为随状态改变而改变的场景,这些都只是涉及到状态而已,即是否可以改变状态和改变成什么状态,不涉及到其他的逻辑
GoodsState:状态类,把商品状态封装成一个类对象,不同的状态就是不同的类,定义了方法:
1. 把商品改成当前的状态;
2. 在当前状态下是否有可以执行某个操作
各个状态实现类自己实现逻辑
GoodsStateManager: 统一的状态流转组件,知道商品流转的所有逻辑,商品执行了什么操作,会改变成什么状态,这个组件定义:
1. 商品执行什么操作,要把商品改成对应的状态,这个调用不同的状态实现类就可以了
2. 根据当前商品状态,判断是否有执行某个操作的权限,这个需要一个同一个的方法或者工厂,根据不同的状态返回不同的实现类
GoodsStateFactory:状态工厂,根据商品的当前状态,返回对应的状态组件,省去了在判断是否可以执行某个操作时,对应的一堆if else
/**
* 待审核商品状态
*/
@Component
public class WaitForApproveGoodsState implements GoodsState {
// 把商品改为待审核状态
@Override
public void doTransition(GoodsDTO goods) throws Exception {
goods.setStatus(GoodsStatus.WAIT_FOR_APPROVE);
goods.setGmtModified(dateProvider.getCurrentTime());
goodsDAO.updateStatus(goods.clone(GoodsDO.class));
}
@Override
public Boolean canEdit(GoodsDTO goods) throws Exception {
return true; //待审核状态可以编辑
}
@Override
public Boolean canApprove(GoodsDTO goods) throws Exception {
return true; //待审核状态可以审核
}
@Override
public Boolean canPutOnShelves(GoodsDTO goods) throws Exception {
return false; //待审核状态不可以上架
}
@Override
public Boolean canPullOffShelves(GoodsDTO goods) throws Exception {
return false; //待审核状态不可以下架
}
@Override
public Boolean canRemove(GoodsDTO goods) throws Exception {
return true; //待审核状态可以删除
}
}
@Component
public class GoodsStateManagerImpl implements GoodsStateManager{
@Override
public void create(GoodsDTO goods) throws Exception {
//商品创建应该把商品改为待审核,所以调用待审核组件
waitForApproveGoodsState.doTransition(goods);
}
//根据商品的当前状态,获取对应的组件,组件里面有判断是否可以编辑的方法
@Override
public Boolean canEdit(GoodsDTO goods) throws Exception {
GoodsState goodsState=goodsStateFactory.get(goods);
return goodsState.canEdit(goods);
}
//商品审核通过应该把商品改为待上架
//商品不审核通过应该把商品改为审核不通过
@Override
public void approve(GoodsDTO goods, Integer approveResult) throws Exception {
if(ApproveResult.APPROVE_PASS.equals(approveResult)){
waitForPutOnShelvesGoodsState.doTransition(goods);
}else {
approveRejectGoodsState.doTransition(goods);
}
}
........
}
GoodsStateFactory工厂
public GoodsState get(GoodsDTO goods){
if(GoodsStatus.WAIT_FOR_APPROVE.equals(goods.getStatus())){
return waitForApproveGoodsState;
}else if(GoodsStatus.APPROVE_REJECT.equals(goods.getStatus())){
return approveRejectGoodsState;
}else if(GoodsStatus.PUTTED_ON_SHELVES.equals(goods.getStatus())){
return puttedOnShelvesGoodsState;
}else if(GoodsStatus.WAIT_FOR_PUT_ON_SHELVES.equals(goods.getStatus())){
return waitForPutOnShelvesGoodsState;
}else {
return defaultGoodsState;
}
}
7.基于责任链模式完成采购入库单审核功能
类图
代码编写
PurchaseInputOrderHandler:责任链接口,定义了执行的方法
AbstractPurchaseInputOrderHandler: 接口的抽象基类,定义下一个处理者变量,具体的业务逻辑执行方法
1. 执行一下本handler的逻辑,定成抽象方法,各自去实现
2. 执行下一个handler的逻辑,调用抽象基类实现的接口方法
UpdateStockHandler: 具体的逻辑实现类
PurchaseInputOrderHandlerFactory :构建责任链工厂,执行的顺序在这里设好,设置一个实现类的下一个处理者是谁
service方法入口
public void approve(Long id, Integer approveResult) throws Exception {
if(PurchaseInputOrderApproveResult.REJECTED.equals(approveResult)) {
purchaseInputOrderDAO.updateStatus(id, PurchaseInputOrderStatus.EDITING);
return;
}
if(PurchaseInputOrderApproveResult.PASSED.equals(approveResult)) {
PurchaseInputOrderDTO purchaseInputOrder = getById(id);
PurchaseInputOrderHandler handlerChain = handlerFactory.getHandlerChain();
handlerChain.execute(purchaseInputOrder);
}
}
责任链构建工厂
@Component
public class PurchaseInputOrderHandlerFactory {
public PurchaseInputOrderHandler getHandlerChain() throws Exception {
buildHandlerChain();
return updatePurchaseInputOrderStatusHandler;
}
// 构造handler链条
private void buildHandlerChain() throws Exception {
//设置对应的下一个处理者
updatePurchaseInputOrderStatusHandler.setSuccessor(informPurchaseCenterHandler);
informPurchaseCenterHandler.setSuccessor(updateStockHandler);
updateStockHandler.setSuccessor(informScheduleCenterHandler);
informScheduleCenterHandler.setSuccessor(informFinanceCenterHandler);
}
}
抽象基类
/**
* 采购入库单责任链基类
* 1.执行本handler的逻辑,2.执行下一个handler的逻辑
*/
public abstract class AbstractPurchaseInputOrderHandler implements PurchaseInputOrderHandler {
//责任链的下一个处理者
protected PurchaseInputOrderHandler successor;
@Override
public Boolean execute(PurchaseInputOrderDTO purchaseInputOrder) throws Exception {
//1. 执行本地handler的逻辑
PurchaseInputOrderHandlerResult result=doExcute(purchaseInputOrder);
//2. 判断下一个处理者是否为空,或者是否设置了执行下一个handler
// 如果有则执行下一个的处理者方法,没有则返回结果
if(successor != null && result.getDoNext()){
//调用下一个处理者的逻辑,还是回到这个方法来,去执行本地逻辑
return successor.execute(purchaseInputOrder);
}else {
return result.getResult();
}
}
protected abstract PurchaseInputOrderHandlerResult doExcute(PurchaseInputOrderDTO purchaseInputOrder)throws Exception;
public void setSuccessor(PurchaseInputOrderHandler successor) {
this.successor = successor;
}
}
具体实现类
/**
* 更新自己本地的库存
*/
public class UpdateStockHandler extends AbstractPurchaseInputOrderHandler {
@Autowired
WmsStockUpdaterFactory wmsStockUpdaterFactory;
@Override
protected PurchaseInputOrderHandlerResult doExcute(PurchaseInputOrderDTO purchaseInputOrder) throws Exception {
WmsStockUpdater stockUpdater=wmsStockUpdaterFactory.
create(WmsStockUpdateEvent.PURCHASE_INPUT,purchaseInputOrder);
stockUpdater.update();
return new PurchaseInputOrderHandlerResult(true);
}
}
通过doNext参数的控制,可以设置是否要执行下一个handler
/**
* handler执行结果
*/
public class PurchaseInputOrderHandlerResult {
//执行结果
private Boolean result;
//是否要执行下一handler
private Boolean doNext=true;
public PurchaseInputOrderHandlerResult(Boolean result) {
this.result = result;
}
public PurchaseInputOrderHandlerResult(Boolean result, Boolean donext) {
this.result = result;
this.doNext = donext;
}
}
8.基于装饰器模式重构订单状态日志功能
类图
代码编写
OrderStateManager:订单状态管理器接口
OrderStateManagerImpl: 订单状态的实现类
LoggedOrderStateManager: 订单状态的增强类,跟OrderStateManagerImp实现同一接口,方法的实现是调用OrderStateManagerImpl的方法,完成后加上日志
service入口
public Boolean informReturnGoodsWorksheetRejectedEvent(Long orderId) {
try {
OrderInfoDTO order=orderInfoService.getById(orderId);
loggedOrderStateManager.rejectReturnGoodsApply(order);
returnGoodsApplyDAO.updateStatus(orderId, ReturnGoodsApplyStatus.REJECTED);
return true;
}catch (Exception e){
logger.error("error",e);
return false;
}
}
增强类方法
@Component
public class LoggedOrderStateManager implements OrderStateManager {
@Autowired
OrderStateManagerImpl orderStateManager;
@Autowired
OrderOperateLogDAO orderOperateLogDAO;
@Autowired
OrderOperateLogFactory orderOperateLogFactory;
@Override
public void create(OrderInfoDTO order) throws Exception {
orderStateManager.create(order); //调用原本的实现类方法
//加入日志功能
orderOperateLogDAO.save(orderOperateLogFactory.get(order, OrderOperateType.CANCEL_ORDER));
}
}
原本的实现类方法
@Component
public class OrderStateManagerImpl implements OrderStateManager {
/**
* 待付款状态
*/
@Autowired
private WaitForPayOrderState waitForPayOrderState;
//创建订单时的状态变更
@Override
public void create(OrderInfoDTO order) throws Exception {
waitForPayOrderState.doTransition(order);
}
}
9基于代理模式完成物流第三方接口
类图
代码编写
LogisticApi :物流接口代理:代理了远程的第三方厂商的所有api接口
LogisticApiImpl :本地的代理实现类,要求统一的传参,和统一的出参
CreateEorderRequest : 统一的传参 ,自己拿到参数,再根据第三方实际要求的格式组装好了去请求
CreateEorderResponse : 统一的出参,拿到第三方请求结果,再封装成自己的返回参数
QueryProgressRequest : 统一的传参,查询接口同上
QueryProgressResponse : 统一的出参,查询接口同上
代理实现类
public class LogisticApiImpl implements LogisticApi {
/**
* 创建电子面单
* @param request 请求
* @return 响应
* @throws Exception
*/
@Override
public CreateEorderResponse createEOrder(CreateEorderRequest request) throws Exception {
// 将request转换成物流商api指定的json请求的格式
// 发送请求到物理商api接口
// 获取到物流商api接口返回的结果,从结果中提取出来对应的信息
// 将响应结果封装成CreateEOrderResponse即可
CreateEorderResponse response = new CreateEorderResponse();
response.setStatus(CreateEorderResponse.SUCCESS);
response.setLogisticCode(UUID.randomUUID().toString().replace("-", ""));
response.setLogisticOrderContent("测试物流单内容");
return response;
}
}