设计模式使用笔记

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;
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值