设计模式

您所在的位置:网站首页 java常用api使用策略模式的例子是什么 设计模式

设计模式

2024-07-14 12:54| 来源: 网络整理| 查看: 265

超级链接: Java常用设计模式的实例学习系列-绪论

参考:《HeadFirst设计模式》

1.关于策略模式

策略模式是一种行为模式。

策略模式:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

如果某种行为拥有多种运作方式,那么把这种行为视为一种策略,把这些运作方式视为策略实现,这些策略实现之间可以相互替换。

这样,行为调用方就可以在运行时,根据不同的需求,将相应的策略实现当做参数,以达到行为按照某种方式运作的目的。

本文以购物车的支付策略为场景来学习策略模式:

每个商品都有名称和价钱。购物车可以添加多个商品。购物车支付方式暂时只支持支付宝和微信,但是后期可能会增减更多支付方式。 2.关于商品

由于本文的关注对象是设计模式,所以这里直接列出商品的代码。

商品:Goods

/** *

商品

* * @author hanchao */ @Setter @Getter @AllArgsConstructor public class Goods { /** * 商品名称 */ private String name; /** * 商品价格 */ private Float price; } 3.不采用策略模式的购物车 3.1.代码

购物车:OrdinaryShoppingCart

/** *

购物车(普通版本)

* * @author hanchao */ @Slf4j public class OrdinaryShoppingCart { /** * 商品列表 */ private List goodsList; public OrdinaryShoppingCart() { goodsList = new ArrayList(); } /** * 添加商品 */ public OrdinaryShoppingCart addGoods(Goods goods) { goodsList.add(goods); return this; } /** * 计算总价 */ public float totalCost() { return goodsList.stream().map(Goods::getPrice).reduce(Float::sum).orElse(0f); } /** * 通过支付宝支付 */ public void payWithAlipay() { log.info("通过支付宝支付了" + totalCost() + "元."); } /** * 通过微信支付 */ public void payWithWeChat() { log.info("通过微信支付了" + totalCost() + "元."); } } 因为有多种支付方式,所以每种支付方式分表编写了一个方法。

测试代码:ShoppingCartDemo

/** *

购物车场景测试

* * @author hanchao */ public class ShoppingCartDemo { public static void main(String[] args) { //购物车(普通版本) //张三的购物行为 new OrdinaryShoppingCart() .addGoods(new Goods("一箱牛奶", 34.55f)) .addGoods(new Goods("一瓶白酒", 250.50f)) .payWithAlipay(); //李四的购物行为 new OrdinaryShoppingCart() .addGoods(new Goods("一箱牛奶", 34.55f)) .addGoods(new Goods("一瓶啤酒", 3.50f)) .payWithWeChat(); } }

运行结果:

2019-07-02 15:53:48,424 INFO [main-1] pers.hanchao.designpattern.strategy.ordinary.OrdinaryShoppingCart:44 - 通过支付宝支付了285.05元. 2019-07-02 15:53:48,429 INFO [main-1] pers.hanchao.designpattern.strategy.ordinary.OrdinaryShoppingCart:51 - 通过微信支付了38.05元. 3.2.分析

优点:

实现简单:代码逻辑很简单,并且只需要编写一个类即可。

缺点:

扩展性差,每增减一种支付方式,都需要修改OrdinaryShoppingCart,违背了设计模式的开放-封闭原则(OCP,对扩展开放,对修改关闭)。可复用低,每种支付方式都采用不同的方法命名。 4.采用策略模式的购物车 4.1.代码

策略模式的关键在于:将行为及其运作方式抽象为策略和策略实现。对于本场景而言,

支付就是一种行为,可以将其视为一种策略,即:支付策略。支付宝支付和微信支付都是支付行为的不同运作方式,可以分别将其视为一种策略实现。

支付策略:PayStrategy

/** *

支付策略

* * @author hanchao */ public interface PayStrategy { /** * 支付 * * @param cost 支付金额 */ void pay(Float cost); }

支付策略实现一:支付宝

/** *

支付宝支付策略

* * @author hanchao */ @Slf4j public class AliPayStrategy implements PayStrategy { @Override public void pay(Float cost) { log.info("通过支付宝支付了" + cost + "元."); } }

支付策略实现二:微信

/** *

微信支付策略

* * @author hanchao */ @Slf4j public class WeChatPayStrategy implements PayStrategy { @Override public void pay(Float cost) { log.info("通过微信支付了" + cost + "元."); } }

购物车(策略模式版本):StrategyShoppingCart

/** *

购物车(策略模式版本)

* * @author hanchao */ @Slf4j public class StrategyShoppingCart { /** * 商品列表 */ private List goodsList; /** * 支付策略 */ private PayStrategy payStrategy; public StrategyShoppingCart() { goodsList = new ArrayList(); } /** * 添加商品 */ public StrategyShoppingCart addGoods(Goods goods) { goodsList.add(goods); return this; } /** * 计算总价 */ public float totalCost() { return goodsList.stream().map(Goods::getPrice).reduce(Float::sum).orElse(0f); } /** * 选择支付策略 */ public StrategyShoppingCart setPayStrategy(PayStrategy payStrategy) { this.payStrategy = payStrategy; return this; } /** * 支付 */ public void pay() { if (Objects.isNull(payStrategy)) { throw new IllegalStateException("未选择支付策略"); } else { payStrategy.pay(totalCost()); } } } 将策略(抽象类/接口)PayStrategy作为客户端StrategyShoppingCart的成员变量,如此才能承载不同的策略实现。提供策略实现的setter方法setPayStrategy(PayStrategy payStrategy),为策略实现的切换提供入口。

测试代码:ShoppingCartDemo

/** *

购物车场景测试

* * @author hanchao */ public class ShoppingCartDemo { public static void main(String[] args) { //购物车(策略模式版本) //王五的购物行为 new StrategyShoppingCart() .addGoods(new Goods("一箱牛奶", 34.55f)) .addGoods(new Goods("一瓶白酒", 250.50f)) .setPayStrategy(new AliPayStrategy()).pay(); //赵六的购物行为 new StrategyShoppingCart() .addGoods(new Goods("一箱牛奶", 34.55f)) .addGoods(new Goods("一瓶啤酒", 3.50f)) .setPayStrategy(new WeChatPayStrategy()).pay(); } }

运行结果:

2019-07-02 17:47:07,309 INFO [main-1] pers.hanchao.designpattern.strategy.strategy.strategy.impl.AliPayStrategy:15 - 通过支付宝支付了285.05元. 2019-07-02 17:47:07,310 INFO [main-1] pers.hanchao.designpattern.strategy.strategy.strategy.impl.WeChatPayStrategy:15 - 通过微信支付了38.05元.

新需求:新的支付方式:银联支付

当新的需求产生,比方说,新增一种支付方式:银联支付。

此时,只需要新增一种支付策略实现UnionPayStrategy即可,无需修改原有代码。

新的支付策略实现三:UnionPayStrategy

/** *

银联支付策略

* * @author hanchao */ @Slf4j public class UnionPayStrategy implements PayStrategy { @Override public void pay(Float cost) { log.info("通过银联支付了" + cost + "元."); } }

测试代码:ShoppingCartDemo

/** *

购物车场景测试

* * @author hanchao */ public class ShoppingCartDemo { public static void main(String[] args) { //购物车(策略模式版本) //孙七的购物行为 new StrategyShoppingCart() .addGoods(new Goods("一箱牛奶", 34.55f)) .addGoods(new Goods("一双袜子", 23.50f)) .setPayStrategy(new UnionPayStrategy()).pay(); } }

运行结果:

2019-07-02 17:55:51,102 INFO [main-1] pers.hanchao.designpattern.strategy.strategy.strategy.impl.UnionPayStrategy:15 - 通过银联支付了58.05元. 4.2.分析

优点:

扩展性好,每增减一种支付方式,只需增减一种支付策略实现即可,无需修改OrdinaryShoppingCart,遵从了设计模式的开放-封闭原则(OCP,对扩展开放,对修改关闭)。可复用高,每种支付方式都采用相同的方法命名。

缺点:

实现复杂:如果有n种策略,则需要n个策略实现类,再加一个策略类。 5.实际案例

HystrixCommand熔断器的默认隔离侧率是线程池隔离,可以通过setter方法修改为信号量隔离,代码如下:

super(Setter .withGroupKey(HystrixCommandGroupKey.Factory.asKey("myGroupKey")) .andCommandPropertiesDefaults( HystrixCommandProperties.Setter() //选择隔离策略:信号量 .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE) ) ); 6.总结

最后以UML类图来总结本文的购物车付款场景以及策略模式。

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3