策略模式(Strategy Pattern)
一.策略模式定义
1.Context封装角色
它也叫上下文,起承上启下的封装作用,屏蔽高层模块对策略、算法的直接访问,封装肯存在变化。
2.Strategy抽象策略角色
策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
3.ConcreteStrategy具体策略角色
实现抽象策略中的操作,改了包含具体的实现等算法或业务特色。
二. 示例
1.抽象的策略角色
/*** 抽象策略角色*/
public interface Strategy {/*** 策略模式算法或者业务特色的控制*/void dosomething();}
2.具体策略角色
public class ConcreteStrateg1 implements Strategy{@Overridepublic void dosomething() {//TODO 实现策略或者具体的业务逻辑}
}public class ConcreteStrateg2 implements Strategy{@Overridepublic void dosomething() {//TODO 实现策略或者具体的业务逻辑}
}
3.封装角色
/*** 封装角色*/
public class Context {private Strategy strategy = null;public Context(Strategy strategy) {this.strategy = strategy;}public void doAnything() {this.strategy.dosomething();}
}
4.高层模块使用
public class Client {public static void main(String[] args) {//声明一个具体的策略Strategy strategy = new ConcreteStrateg1();//声明上下文Context context = new Context(strategy);//执行封装后的方法}
}
三.应用场景
1.电商平台购物车渲染
(1)定义购物车渲染枚举
/*** 购物车渲染枚举*/
public enum RenderStepEnums {/*** 购物车渲染枚举*/CHECK_DATA("校验商品"),CHECKED_FILTER("选择商品过滤"),COUPON("优惠券价格渲染"),SKU_PROMOTION("商品促销计算"),FULL_DISCOUNT("满减计算"),SKU_FREIGHT("运费计算"),DISTRIBUTION("分配需要分配的促销金额"),PLATFORM_COMMISSION("平台佣金"),CART_PRICE("购物车金额计算"),CART_SN("交易编号创建");private String distribution;public String getDistribution() {return distribution;}RenderStepEnums(String distribution) {this.distribution = distribution;}
}
(2)抽象购物车渲染步骤策略
/*** 购物车渲染*/
public interface CartRenderStep {/*** 渲染价格步骤** @return 渲染枚举*/RenderStepEnums step();/*** 渲染一笔交易** @param tradeDTO 交易DTO*/void render(Object tradeDTO);}
(3)实现购物车渲染的业务逻辑
/*** 购物车渲染,将购物车中的各个商品,拆分到每个商家,形成购物车VO*/
public class CartPriceRender implements CartRenderStep {@Overridepublic RenderStepEnums step() {return RenderStepEnums.CART_PRICE;}@Overridepublic void render(Object tradeDTO) {//TODO 计算商品价格等}
}
/*** 交易流水号生成*/
public class CartSnRender implements CartRenderStep {@Overridepublic RenderStepEnums step() {return RenderStepEnums.CART_SN;}@Overridepublic void render(Object tradeDTO) {//生成流水号等等}
}
/*** sku 运费计算**/
public class SkuFreightRender implements CartRenderStep {@Overridepublic RenderStepEnums step() {return RenderStepEnums.SKU_FREIGHT;}@Overridepublic void render(TradeDTO tradeDTO) {//收货地址问题处理、校验等//运费模板选择等//选择物流的时候计算价格}
}
(4)封装购物车渲染策略
public class RenderStepContext {/*** spring的直接注入列表就可以了,其他的通过构造函数等方式初始化策略* 购物车渲染步骤*///@Autowiredprivate List<CartRenderStep> cartRenderSteps;public RenderStepContext() {}public RenderStepContext(List<CartRenderStep> cartRenderSteps) {this.cartRenderSteps = cartRenderSteps;}public void renderCartBySteps(Object dto, RenderStepEnums[] renderSteps) {for (RenderStepEnums step : renderSteps) {for (CartRenderStep render : cartRenderSteps) {try {if (render.step().equals(step)) {render.render(dto);}} catch (Exception e) {throw e;}}}}
}
(5)根据业务场景选择策略
/*** 购物车渲染 步骤声明**/
public class RenderStepStatement {/*** 测试*/public static RenderStepEnums[] test = {RenderStepEnums.CART_PRICE,RenderStepEnums.CART_SN};/*** 购物车购物车渲染* 校验商品 》 满优惠渲染 》 渲染优惠 》计算价格*/public static RenderStepEnums[] cartRender = {RenderStepEnums.CHECK_DATA,RenderStepEnums.SKU_PROMOTION,RenderStepEnums.FULL_DISCOUNT,RenderStepEnums.CART_PRICE};/*** 结算页渲染* 过滤选择的商品 》 校验商品 》 满优惠渲染 》 渲染优惠 》* 优惠券渲染 》 计算运费 》 计算价格*/public static RenderStepEnums[] checkedRender = {RenderStepEnums.CHECKED_FILTER,RenderStepEnums.CHECK_DATA,RenderStepEnums.SKU_PROMOTION,RenderStepEnums.FULL_DISCOUNT,RenderStepEnums.COUPON,RenderStepEnums.SKU_FREIGHT,RenderStepEnums.CART_PRICE,};/*** 单个商品优惠,不需要渲染满减优惠* 用于特殊场景:例如积分商品,拼团商品,虚拟商品等等*/public static RenderStepEnums[] checkedSingleRender = {RenderStepEnums.CHECK_DATA,RenderStepEnums.SKU_PROMOTION,RenderStepEnums.COUPON,RenderStepEnums.SKU_FREIGHT,RenderStepEnums.CART_PRICE};/*** 交易创建前渲染* 渲染购物车 生成SN 》分销人员佣金渲染 》平台佣金渲染*/public static RenderStepEnums[] singleTradeRender = {RenderStepEnums.CHECK_DATA,RenderStepEnums.SKU_PROMOTION,RenderStepEnums.SKU_FREIGHT,RenderStepEnums.CART_PRICE,RenderStepEnums.CART_SN,RenderStepEnums.DISTRIBUTION,RenderStepEnums.PLATFORM_COMMISSION};/*** 交易创建前渲染* 渲染购物车 生成SN 》分销人员佣金渲染 》平台佣金渲染*/public static RenderStepEnums[] pintuanTradeRender = {RenderStepEnums.CHECK_DATA,RenderStepEnums.SKU_PROMOTION,RenderStepEnums.COUPON,RenderStepEnums.SKU_FREIGHT,RenderStepEnums.CART_PRICE,RenderStepEnums.CART_SN,RenderStepEnums.DISTRIBUTION,RenderStepEnums.PLATFORM_COMMISSION};/*** 交易创建前渲染* 渲染购物车 生成SN 》分销人员佣金渲染 》平台佣金渲染*/public static RenderStepEnums[] tradeRender = {RenderStepEnums.CHECKED_FILTER,RenderStepEnums.CHECK_DATA,RenderStepEnums.SKU_PROMOTION,RenderStepEnums.FULL_DISCOUNT,RenderStepEnums.COUPON,RenderStepEnums.SKU_FREIGHT,RenderStepEnums.CART_PRICE,RenderStepEnums.CART_SN,RenderStepEnums.DISTRIBUTION,RenderStepEnums.PLATFORM_COMMISSION};
}
(6)高层业务模块使用
public class StrategyTest {public static void main(String[] args) {List<CartRenderStep> stepList = new ArrayList<>();stepList.add(new CartPriceRender());stepList.add(new CartSnRender());RenderStepContext context = new RenderStepContext(stepList);context.renderCartBySteps(new Object(), RenderStepStatement.test);}
}