委派模式和策略模式
Posted zekichen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了委派模式和策略模式相关的知识,希望对你有一定的参考价值。
一、委派模式
委派模式(Delegate Pattern):指负责任务的调度和分配任务,跟代理模式很像,可以看做是一种特殊情况下的静态代理的全权代理,但是代理模式注重过程,而委派模式注重结果。(属于行为型模式,但它不属于GOF的23种设计模式之一。类名以Delegate和Dispatcher结尾的一般都是委派模式)
委派模式在Spring中应用非常多,大家常用的DispatcherServlet其实就用到了委派模式。现实生活中也常有委派的场景发生,例如:老板(Boss)给项目经理(Leader)下达任务,项目经理会根据实际情况给每个员工派发工作任务,待员工把工作任务完成之后,再由项目经理汇报工作进度和结果给老板,业务场景如下图:
例子1:用代码来模拟一下这个业务场景,定义一个IEmployee员工接口:
定义一个员工EmployeeA类:
定义一个员工EmployeeB类:
定义一个项目经理Leader类:
定义一个Boss类下达命令:
测试代码:
运行结果:
类结构图:
通过上面的代码,生动地还原了项目经理分配工作的业务场景,也是委派模式的生动体现。
委派模式在源码中的体现
例子2:还原SpirngMVC的DispatcherServlet是如何实现委派模式的。定义一个MemberController类 :
定义一个OrderController类:
定义一个DispatcherServlet类:
配置web.xml文件:
二、策略模式
1、策略模式(Strategy pattern):指定义了算法家族、分别封装起来,让它们之间可以相互替换,此模式让算法的变化不会影响到使用算法的用户。(属于行为型模式)
2、适用场景
- 假如系统中有很多类,而他们的区别仅仅在于他们的行为不同
- 一个系统需要动态地在几种算法中选择一种
3、优点
- 策略模式符合开闭原则
- 避免使用多重条件转移语句,如if...else...和switch语句
- 使用策略模式可以提高算法的保密性和安全性
4、缺点
- 客户端必须知道所有的策略,并且自行决定使用哪一个策略类
- 代码中产生非常多策略类,增加维护难度
例子1:有一个课程优惠活动,优惠策略会有多种,如领优惠券抵扣、返现促销等。下面用代码来模拟:
定义一个促销策略PromotionStragegy接口:
定义一个优惠券折扣策略CouponStragegy类:
定义一个返现促销策略CashbackStrategy类:
定义一个无优惠EmptyStrategy类:
定义一个促销活动方案PromotionActivity类:
编写客户端测试类:
此时大家会发现,如果把上面这段测试代码放到实际的业务场景其实并不实用。因为我们做活动时往往是根据不同的需求对促销策略进行动态选择的,并不会一次性执行多种优惠。所以,我们的代码通常会这样写:
这样改造之后,满足了业务需求,客户可根据自己的需求选择不同的优惠策略了。但是,经过一段时间的业务积累,我们的促销活动会越来越多。于是,我们的程序猿小哥哥就忙不赢了,每次上活动之前都要通宵改代码,而且要做重复测试,判断逻辑可能也变得越来越复杂。这时候,我们可以结合之前学过的单例模式和工厂模式。定义一个策略工厂PromotionStrategyFactory类:
这时候客户端代码就应该这样写了:
类结构图:
代码优化之后,程序猿小哥哥维护工作就轻松多了,每次上新活动,不影响原来的代码逻辑。
例子2:一个常见的应用场景就是大家在下单支付时会提示选择支付方式,如果用户未选,系统也会使用默认推荐的支付方式进行结算。
定义一个支付渠道Payment抽象类,声明支付规范和支付逻辑:
定义具体的支付方式,支付宝AliPay类:
微信支付WechatPay类:
定义一个支付状态的包装类PayState:
定义一个支付策略管理PayStrategy类:
定义一个Order订单类:
测试代码:
运行结果:
三、委派模式与策略模式综合应用
回顾一下DispatcherServlet的委派逻辑,代码如下:
这样的代码扩展性不太优雅,也不现实,因为我们实际项目中一定不止这几个Controller,往往是成千上万个Controller,显然我们不能写成千上万个if...else...。那么我们可以结合策略模式改造优化一下:
定义一个Handler类:
改造DispatcherServlet类:
上面的代码结合了委派、策略、工厂、单例模式。
以上是关于委派模式和策略模式的主要内容,如果未能解决你的问题,请参考以下文章