template method 模板模式
他们共同的基础逻辑抽取到父类中,然后将要子类实现的逻辑留空,交给子类去实现。
场景:
(1)我们有多种优惠策略
(2)不同的优惠策略在计算的价格的时候,有一些通用的基础逻辑
(3)每种优惠策略还有一些是自己特殊的价格计算的逻辑

简单工厂模式
工厂模式的核心思想,其实就是不要自己在代码里手动new一个实现类对象出来,因为那样的话,调用方就不是面向接口编程了,你还得自己去care实现了

复杂工厂模式:模板+复杂工厂模式
factory method模式:模板方法模式+简单工厂模式,简单工厂模式稍微复杂一点的变种

抽象工厂模式
abstract factory模式 -> 简单工厂模式的变种 -> 最复杂的一个变种
场景:
(1)就是我们现在要生产的不是一个一个产品,而一个一个的产品组合
(2)比如说我们有产品ABC,现在第一种产品组合是A+B,第二种产品组合是B+C,第三种产品组合是A+Cs
(3)就是要对工厂模式进行进一步的增强

需求背景
实现库存的管理,有入库单,退货单。

1、库存系统收到这2种不同的事件,可以做出不同的反应 —命令模式,不同的事件对应不同的命令

2、根据输入的事件,不用自己去new 相应的命令commond–简单工厂模式

3、new 不同的命令入库单命令,有一些函数是可以共用的,因此可以抽取出一个AbstractFactory 就是复杂工厂

4、不同的入库出库单,有一些共性的函数,比如更新时间,比如最后都要调用DAO更新数据库,这些共同的东西也可以抽取出公共的AbstractCommand,非公共的则定义好abstract函数,交给子类的Command去实现—模板模式

/**
 * 商品库存更新命令的接口
 * @author 
 *
 */
public interface GoodsStockUpdateCommand {

	/**
	 * 更新商品库存
	 * @return 处理结果
	 */
	Boolean updateGoodsStock();
	
}
/**
 * 库存更新命令工厂接口
 * @author 
 *
 */
public interface GoodsStockUpdateCommandFactory<T> { 

	/**
	 * 创建一个库存更新命令
	 * @param parameter 参数对象
	 * @return 库存更新命令
	 */
	GoodsStockUpdateCommand create(T parameter);
	
}

/**
 * 商品库存更新命令的抽象基类
 * @author
 *
 */
public abstract class AbstractGoodsStockUpdateCommand implements GoodsStockUpdateCommand {

	private static final Logger logger = LoggerFactory.getLogger(
			AbstractGoodsStockUpdateCommand.class);
	
	/**
	 * 商品库存DO对象
	 */
	protected List<GoodsStockDO> goodsStockDOs;
	
	/**
	 * 商品库存管理模块的DAD组件
	 */
	protected GoodsStockDAO goodsStockDAO;
	
	/**
	 * 日期辅助组件
	 */
	protected DateProvider dateProvider;
	
	/**
	 * 构造函数
	 * @param goodsStockDO 商品库存DO对象
	 * @param goodsStockDAO 商品库存管理模块的DAO组件
	 * @param dateProvider 日期辅助组件
	 */
	public AbstractGoodsStockUpdateCommand(
			List<GoodsStockDO> goodsStockDOs,
			GoodsStockDAO goodsStockDAO,
			DateProvider dateProvider) {
		this.goodsStockDOs = goodsStockDOs;
		this.goodsStockDAO = goodsStockDAO;
		this.dateProvider = dateProvider;
	}
	
	/**
	 * 更新商品库存
	 */
	public Boolean updateGoodsStock() {
		try {
			updateSaleStockQuantity();
			updateLockedStockQuantity();
			updateSaledStockQuantity();
			updateStockStatus();
			updateGmtModified();
			executeUpdateGoodsStock();
		} catch (Exception e) {
			logger.error("error", e); 
		}
		return true;
	}
	
	/**
	 * 更新商品的销售库存
	 */
	protected abstract void updateSaleStockQuantity() throws Exception;
	
	/**
	 * 更新商品的锁定库存
	 */
	protected abstract void updateLockedStockQuantity() throws Exception;
	
	/**
	 * 更新商品的已销售库存
	 */
	protected abstract void updateSaledStockQuantity() throws Exception;
	
	/**
	 * 更新商品的库存状态
	 */
	private void updateStockStatus() throws Exception {
		for(GoodsStockDO goodsStockDO : goodsStockDOs) {
			if(goodsStockDO.getSaleStockQuantity() > 0L) {
				goodsStockDO.setStockStatus(StockStatus.IN_STOCK); 
			} else {
				goodsStockDO.setStockStatus(StockStatus.NOT_IN_STOCK); 
			}
		}
	}
	
	/**
	 * 更新商品库存的修改时间
	 */
	private void updateGmtModified() throws Exception {
		for(GoodsStockDO goodsStockDO : goodsStockDOs) {
			goodsStockDO.setGmtModified(dateProvider.getCurrentTime());
		}
	}
	
	/**
	 * 实际执行更新商品库存的操作
	 * @throws Exception
	 */
	private void executeUpdateGoodsStock() throws Exception {
		for(GoodsStockDO goodsStockDO : goodsStockDOs) {
			goodsStockDAO.updateGoodsStock(goodsStockDO);
		}
	}
	
}

/**
 * 库存更新命令工厂的父类
 * @author 
 *
 */
public abstract class AbstractGoodsStockUpdateCommandFactory<T> 
		implements GoodsStockUpdateCommandFactory<T> {
	
	private static final Logger logger = LoggerFactory.getLogger(
			AbstractGoodsStockUpdateCommandFactory.class);

	/**
	 * 商品库存管理模块的DAO组件
	 */
	protected GoodsStockDAO goodsStockDAO;
	
	/**
	 * 日期辅助组件
	 */
	protected DateProvider dateProvider;
	
	/**
	 * 构造函数
	 * @param goodsStockDAO 商品库存管理模块的DAO组件
	 * @param dateProvider 日期辅助组件
	 */
	public AbstractGoodsStockUpdateCommandFactory(
			GoodsStockDAO goodsStockDAO,
			DateProvider dateProvider) {
		this.goodsStockDAO = goodsStockDAO;
		this.dateProvider = dateProvider;
	}
	
	/**
	 * 创建库存更新命令
	 */
	public GoodsStockUpdateCommand create(T parameter) {
		try {
			List<Long> goodsSkuIds = getGoodsSkuIds(parameter);
			List<GoodsStockDO> goodsStockDOs = createGoodsStockDOs(goodsSkuIds);
			return create(goodsStockDOs, parameter); 
		} catch (Exception e) {
			logger.error("error", e); 
		}
		return null;
	}
	
	/**
	 * 获取商品sku id集合
	 * @return 商品sku id集合
	 * @throws Exception
	 */
	protected abstract List<Long> getGoodsSkuIds(T parameter) throws Exception;
	
	/**
	 * 创建库存更新命令
	 * @param goodsStockDOs 商品库存DO对象集合
	 * @return 库存更新命令
	 * @throws Exception
	 */
	protected abstract GoodsStockUpdateCommand create(
			List<GoodsStockDO> goodsStockDOs, T parameter) throws Exception;
	
	/**
	 * 创建商品库存DO对象集合
	 * @param goodsSkuIds 商品sku id集合
	 * @return 商品库存DO对象集合
	 */
	private List<GoodsStockDO> createGoodsStockDOs(List<Long> goodsSkuIds) throws Exception {
		List<GoodsStockDO> goodsStockDOs = new ArrayList<GoodsStockDO>(goodsSkuIds.size());
		
		for(Long goodsSkuId : goodsSkuIds) {
			GoodsStockDO goodsStockDO = goodsStockDAO.getGoodsStockBySkuId(goodsSkuId);
			
			if(goodsStockDO == null) {
				goodsStockDO = new GoodsStockDO();
				goodsStockDO.setGoodsSkuId(goodsSkuId);
				goodsStockDO.setSaleStockQuantity(0L);
				goodsStockDO.setLockedStockQuantity(0L); 
				goodsStockDO.setSaledStockQuantity(0L);
				goodsStockDO.setStockStatus(StockStatus.NOT_IN_STOCK); 
				goodsStockDO.setGmtCreate(dateProvider.getCurrentTime());
				goodsStockDO.setGmtModified(dateProvider.getCurrentTime());  
				
				goodsStockDAO.saveGoodsStock(goodsStockDO);
 			}
			
			goodsStockDOs.add(goodsStockDO);
		}
		
		return goodsStockDOs;
	}
	
}

/**
 * 采购入库库存更新命令
 * @author 
 *
 */
public class PurchaseInputStockUpdateCommand extends AbstractGoodsStockUpdateCommand {

	/**
	 * 采购入库单条目DTO集合
	 */
	private Map<Long, PurchaseInputOrderItemDTO> purcahseInputOrderItemDTOMap;
	
	/**
	 * 构造函数
	 * @param goodsStockDO 商品库存DO对象
	 * @param goodsStockDAO 商品库存管理模块的DAO组件
	 * @param dateProvider 日期辅助组件
	 */
	public PurchaseInputStockUpdateCommand(
			List<GoodsStockDO> goodsStockDOs, 
			GoodsStockDAO goodsStockDAO,
			DateProvider dateProvider,
			Map<Long, PurchaseInputOrderItemDTO> purcahseInputOrderItemDTOMap) {
		super(goodsStockDOs, goodsStockDAO, dateProvider);
		this.purcahseInputOrderItemDTOMap = purcahseInputOrderItemDTOMap;
	}
	
	/**
	 * 更新销售库存
	 */
	@Override
	protected void updateSaleStockQuantity() throws Exception {
		for(GoodsStockDO goodsStockDO : goodsStockDOs) {
			PurchaseInputOrderItemDTO purchaseInputOrderItemDTO = 
					purcahseInputOrderItemDTOMap.get(goodsStockDO.getId());
			goodsStockDO.setSaleStockQuantity(goodsStockDO.getSaleStockQuantity() 
					+ purchaseInputOrderItemDTO.getArrivalCount()); 
		}
	}

	/**
	 * 更新锁定库存
	 */
	@Override
	protected void updateLockedStockQuantity() throws Exception {
		
	}

	/**
	 * 更新已销售库存
	 */
	@Override
	protected void updateSaledStockQuantity() throws Exception {
		
	}

}
/**
 * 采购入库库存更新命令的工厂
 * @author 
 *
 */
@Component
public class PurchaseInputStockUpdateCommandFactory<T> 
		extends AbstractGoodsStockUpdateCommandFactory<T> {
	
	/**
	 * 构造函数
	 * @param goodsStockDAO 商品库存管理模块的DAO组件
	 * @param dateProvider 日期辅助组件
	 */
	@Autowired
	public PurchaseInputStockUpdateCommandFactory(
			GoodsStockDAO goodsStockDAO, 
			DateProvider dateProvider) {
		super(goodsStockDAO, dateProvider);
	}

	/**
	 * 获取商品sku id集合
	 * @return 商品sku id集合
	 * @throws Exception
	 */
	@Override
	protected List<Long> getGoodsSkuIds(T parameter) throws Exception {		
		PurchaseInputOrderDTO purchaseInputOrderDTO = (PurchaseInputOrderDTO) parameter;
		List<PurchaseInputOrderItemDTO> purchaseInputOrderItemDTOs = 
				purchaseInputOrderDTO.getPurchaseInputOrderItemDTOs();
		
		if(purchaseInputOrderItemDTOs == null || purchaseInputOrderItemDTOs.size() == 0) {
			return new ArrayList<Long>();
		}
		
		List<Long> goodsSkuIds = new ArrayList<Long>(purchaseInputOrderItemDTOs.size());
		
		for(PurchaseInputOrderItemDTO purchaseInputOrderItemDTO : purchaseInputOrderItemDTOs) {
			goodsSkuIds.add(purchaseInputOrderItemDTO.getGoodsSkuId());
		}
		
		return goodsSkuIds;
	}

	/**
	 * 创建库存更新命令
	 * @param goodsStockDOs 商品库存DO对象集合
	 * @return 库存更新命令
	 * @throws Exception
	 */
	@Override
	protected GoodsStockUpdateCommand create(
			List<GoodsStockDO> goodsStockDOs,
			T parameter) throws Exception {
		PurchaseInputOrderDTO purchaseInputOrderDTO = (PurchaseInputOrderDTO) parameter;
		List<PurchaseInputOrderItemDTO> purchaseInputOrderItemDTOs = 
				purchaseInputOrderDTO.getPurchaseInputOrderItemDTOs();
		
		Map<Long, PurchaseInputOrderItemDTO> purchaseInputOrderItemDTOMap = 
				new HashMap<Long, PurchaseInputOrderItemDTO>();
		
		if(purchaseInputOrderItemDTOs != null && purchaseInputOrderItemDTOs.size() > 0) {
			for(PurchaseInputOrderItemDTO purchaseInputOrderItemDTO : purchaseInputOrderItemDTOs) {
				purchaseInputOrderItemDTOMap.put(purchaseInputOrderItemDTO.getGoodsSkuId(), 
						purchaseInputOrderItemDTO);
			}
		}
		
		return new PurchaseInputStockUpdateCommand(goodsStockDOs, goodsStockDAO, 
				dateProvider, purchaseInputOrderItemDTOMap); 
	}

}

/**
 * 退货入库
 * @author 
 *
 */
public class ReturnGoodsInputStockUpdateCommand extends AbstractGoodsStockUpdateCommand {

	/**
	 * 退货入库单条目DTO集合
	 */
	private Map<Long, ReturnGoodsInputOrderItemDTO> returnGoodsInputOrderItemDTOMap;
	
	/**
	 * 构造函数
	 * @param goodsStockDOs 商品库存DO集合
	 * @param goodsStockDAO 商品库存管理模块的DAO组件
	 * @param dateProvider 日期辅助组件
	 * @param returnGoodsInputOrderItemDTOMap 退货入库单条目DTO集合
	 */
	public ReturnGoodsInputStockUpdateCommand(
			List<GoodsStockDO> goodsStockDOs, 
			GoodsStockDAO goodsStockDAO,
			DateProvider dateProvider,
			Map<Long, ReturnGoodsInputOrderItemDTO> returnGoodsInputOrderItemDTOMap) {
		super(goodsStockDOs, goodsStockDAO, dateProvider);
		this.returnGoodsInputOrderItemDTOMap = returnGoodsInputOrderItemDTOMap;
	}

	/**
	 * 更新销售库存
	 */
	@Override
	protected void updateSaleStockQuantity() throws Exception {
		for(GoodsStockDO goodsStockDO : goodsStockDOs) {
			ReturnGoodsInputOrderItemDTO returnGoodsInputOrderItemDTO = 
					returnGoodsInputOrderItemDTOMap.get(goodsStockDO.getId());
			goodsStockDO.setSaleStockQuantity(goodsStockDO.getSaleStockQuantity() 
					+ returnGoodsInputOrderItemDTO.getArrivalCount()); 
		}
	}

	/**
	 * 更新锁定库存
	 */
	@Override
	protected void updateLockedStockQuantity() throws Exception {
		
	}

	/**
	 * 更新已销售库存
	 */
	@Override
	protected void updateSaledStockQuantity() throws Exception {
		for(GoodsStockDO goodsStockDO : goodsStockDOs) {
			ReturnGoodsInputOrderItemDTO returnGoodsInputOrderItemDTO = 
					returnGoodsInputOrderItemDTOMap.get(goodsStockDO.getId());
			goodsStockDO.setSaleStockQuantity(goodsStockDO.getSaleStockQuantity() 
					- returnGoodsInputOrderItemDTO.getArrivalCount()); 
		}
	}
	
}
/**
 * 退货入库库存更新命令的工厂
 * @author 
 *
 */
@Component
public class ReturnGoodsInputStockUpdateCommandFactory<T> 
		extends AbstractGoodsStockUpdateCommandFactory<T> {
	
	/**
	 * 构造函数
	 * @param goodsStockDAO 商品库存管理模块的DAO组件
	 * @param dateProvider 日期辅助组件
	 */
	@Autowired
	public ReturnGoodsInputStockUpdateCommandFactory(
			GoodsStockDAO goodsStockDAO, 
			DateProvider dateProvider) {
		super(goodsStockDAO, dateProvider);
	}

	/**
	 * 获取商品sku id集合
	 * @return 商品sku id集合
	 * @throws Exception
	 */
	@Override
	protected List<Long> getGoodsSkuIds(T parameter) throws Exception {		
		ReturnGoodsInputOrderDTO returnGoodsInputOrderDTO = (ReturnGoodsInputOrderDTO) parameter;
		List<ReturnGoodsInputOrderItemDTO> returnGoodsInputOrderItemDTOs = 
				returnGoodsInputOrderDTO.getReturnGoodsInputOrderItemDTOs();
		
		if(returnGoodsInputOrderItemDTOs == null || returnGoodsInputOrderItemDTOs.size() == 0) {
			return new ArrayList<Long>();
		}
		
		List<Long> goodsSkuIds = new ArrayList<Long>(returnGoodsInputOrderItemDTOs.size());
		
		for(ReturnGoodsInputOrderItemDTO returnGoodsInputOrderItemDTO : returnGoodsInputOrderItemDTOs) {
			goodsSkuIds.add(returnGoodsInputOrderItemDTO.getGoodsSkuId());
		}
		
		return goodsSkuIds;
	}

	/**
	 * 创建库存更新命令
	 * @param goodsStockDOs 商品库存DO对象集合
	 * @return 库存更新命令
	 * @throws Exception
	 */
	@Override
	protected GoodsStockUpdateCommand create(
			List<GoodsStockDO> goodsStockDOs,
			T parameter) throws Exception {
		ReturnGoodsInputOrderDTO returnGoodsInputOrderDTO = (ReturnGoodsInputOrderDTO) parameter;
		List<ReturnGoodsInputOrderItemDTO> returnGoodsInputOrderItemDTOs = 
				returnGoodsInputOrderDTO.getReturnGoodsInputOrderItemDTOs();
		
		Map<Long, ReturnGoodsInputOrderItemDTO> returnGoodsInputOrderItemDTOMap = 
				new HashMap<Long, ReturnGoodsInputOrderItemDTO>();
		
		if(returnGoodsInputOrderItemDTOs != null && returnGoodsInputOrderItemDTOs.size() > 0) {
			for(ReturnGoodsInputOrderItemDTO returnGoodsInputOrderItemDTO : returnGoodsInputOrderItemDTOs) {
				returnGoodsInputOrderItemDTOMap.put(returnGoodsInputOrderItemDTO.getGoodsSkuId(), 
						returnGoodsInputOrderItemDTO);
			}
		}
		
		return new ReturnGoodsInputStockUpdateCommand(goodsStockDOs, goodsStockDAO, 
				dateProvider, returnGoodsInputOrderItemDTOMap); 
	}

}
/**
 * 库存中心对外提供接口的service组件
 * @author 
 *
 */
@Service
public class InventoryFacadeServiceImpl implements InventoryFacadeService {
	
	private static final Logger logger = LoggerFactory.getLogger(InventoryFacadeServiceImpl.class);

	/**
	 * 采购入库库存更新命令工厂
	 */
	@Autowired
	private PurchaseInputStockUpdateCommandFactory<PurchaseInputOrderDTO> 
			purchaseInputStockUpdateCommandFactory;
	/**
	 * 退货入库库存更新命令工厂
	 */
	@Autowired
	private ReturnGoodsInputStockUpdateCommandFactory<ReturnGoodsInputOrderDTO> 
			returnGoodsInputStockUpdateCommandFactory;
	
	/**
	 * 通知库存中心,“采购入库完成”事件发生了
	 * @param purchaseInputOrderDTO 采购入库单DTO
	 * @return 处理结果
	 */
	public Boolean informPurchaseInputFinished(
			PurchaseInputOrderDTO purchaseInputOrderDTO) {
		try {
			GoodsStockUpdateCommand goodsStockUpdateCommand = 
					purchaseInputStockUpdateCommandFactory.create(purchaseInputOrderDTO);
			goodsStockUpdateCommand.updateGoodsStock();
		} catch (Exception e) {
			logger.error("error", e); 
			return false;
		}
		return true;
	}
	


	
	/**
	 * 通知库存中心,“完成退货入库”事件发生了
	 * @param returnGoodsInputOrderDTO 退货入库单DTO
	 * @return 处理结果
	 */
	public Boolean informReturnGoodsInputFinished(
			ReturnGoodsInputOrderDTO returnGoodsInputOrderDTO) {
		try {
			GoodsStockUpdateCommand goodsStockUpdateCommand = 
					returnGoodsInputStockUpdateCommandFactory.create(returnGoodsInputOrderDTO);
			goodsStockUpdateCommand.updateGoodsStock();
		} catch (Exception e) {
			logger.error("error", e); 
			return false;
		}
		return true;
	}
	

	
}