-
搞打折活动时,汉堡只需要5块大洋,通过指定链接,把汉堡加到购物车,创建订单,支付,等待出餐
-
搞买一送一活动时,把汉堡添加到购物车,创建订单,支付,等待出餐
-
搞满减活动时,把汉堡和中薯、那么大鸡排添加到购物车,凑足满减金额,创建订单,使用优惠券,支付出餐
通过画图的形式展示一下上述的逻辑
上面是完整的步骤,简化一下,我们只关注产生价值的部分,也就是客户支付了多少钱,取到了哪些食物
进一步说就是,商户可以随意切换形式,比如昨天有5元的板烧,今天点进去看发现没有了,但是多出来了其他的优惠,例如【麦乐鸡20粒】优惠券,后天进去发现优惠券都没了,只能原价购买等情况;但是无论形式是这样的,最终产出时的步骤都是一致的,例如这里就是支付和取餐
绕了这么久,其实就是要引出今天的主角————策略模式
策略模式
====
标准定义以及类图
定义一组算法,并封装每个算法,让它们彼此可以交换使用。策略模式让这些算法在客户端中使用起来更加独立
如果以上述例子来看,所有形式都是一种特定的算法
-
原价购买是一种算法
-
打折也是一种算法
-
优惠券满减也是算法
-
买一送一也是算法
-
…
算法具体的如何实现的,客户端不管,客户端只知道,我可以任意切换形式,并且达成想要的效果
就好比顾客知道有这个活动,但不用知道这个活动的其他细节,我只需要按照步骤操作即可有优惠
尝试编码
====
既然上述几种情况最终都需要支付和取餐,那么我们直接就定义一个顶层接口管理这些算法(相当于是AbstractStrategy),接口中有两个方法
-
一个是返回实际需要付多少钱
-
一个是返回实际取到的食物列表
具体如何实现,就是每个算法内部的事情了,别人管不了,相当于是每一个ConcentrateStrategy
从类图上看到,标准的策略模式还要有一个组件Context,他就类似是策略模式的客户端,要调用哪一个策略,跟Context沟通,不跟具体实现沟通,这样做的好处就是实现客户端(真正的调用方)与具体实现间的解耦,如下图所示
所以,根据设计,我们把代码给敲一下
-
首先是顶层接口代码
-
然后是各个具体算法的实现
-
Context代码
-
客户端调用情况输出结果
如果我要新添加一种形式呢?
=============
麦当劳“壕无人性”地说,今天薯条免费赠送,那么针对这种情况,很明显现有的算法家族是不支持的,那么我们只需要再添加一种算法,叫做【FreePrice】,然后交给Client调用即可
我们完全不需要动其他已经写好的算法,这很符合OCP原则,并且算法的具体实现也被完美的隐藏在各个实现类中,实在是很nice
策略模式的优点
=======
其实刚刚也讲了,这里再总结一下
-
算法的具体实现封装在各个实现类中,客户端不需要知道
-
客户端可以根据场合随意切换到底要使用哪一种策略
-
将客户端与具体实现通过Context解耦,即符合OCP原则,又可以让具体算法独立发展而不会影响其他类修改
策略模式的局限
=======
那么,可能有小伙伴就想提问了,策略模式这么牛逼,他就没有一点局限性吗?这里引用我在看《Head First 设计模式》中看到的一段话,他的意思是
设计模式的定义告诉我们,问题包含了一个目标和一组约束;光明的方向就是你的目标,黑暗的方向就是这些约束
光明与黑暗总是相伴而生,所以策略模式的约束是什么?不妨从我们实际调用的方向入手,思考一下
商户在实际设置新行为的时候,肯定是会有一个UI界面,会有下拉选择本次要推出的形式,针对不同的形式,所需要的参数也不尽相同,例如形式是优惠卷满减的时候,需要有满减阈值,满减多少,优惠券时效等等参数
那么发送到后端创建的时候,url请求也许是这样子的(简单给个例子):newActivity?type=1
其中type就是标识,我们具体选择的策略,比如
-
type=1代表是原价
-
type=2代表是打折
-
type=3代表是满减
然后回看一下刚刚写的代码,在Client端调用,简直就是太过于理想化了,真正调用的时候,不可能这么写的
实际上,对应处理的Controller(客户端)在接收到方法的时候,最基础时要这么来判断
//伪代码,暂不校验字段有效性问题
if (1 == type)
then xxxx
else if (2 == type)
then xxxx
else if (3 == type)
then xxxx
else if (4 == type)
then xxxx
…
你说这个,跟我了解策略模式的局限性到底有什么关系啊?其实仔细品一下,就会发现,尽管我们把各个算法的实现细节都给隐藏了,当时我们依然需要知道有多少种策略,换言之就是,我们在选择策略的时候不免要进行判断,这就是策略模式一个局限
第二个就是,每次都需要新建一个类单独做一个算法策略,如果有很多很多的算法策略,就会导致类结构非常的膨胀,此时,就不易于维护和管理
解决局限性问题
=======
针对客户端存在一大堆的if-else,我们使用简单工厂的形式配合把他们都封装起来
简单工厂+策略模式解决客户端大量if-else情况
=========================
原来的设计不变,把Context给替换成HandlerFactory,通过静态方法返回信息,这里为了更加贴合实际,定义了两个VO对象
简单工厂
最终客户端调用
使用postman进行测试,为了方便起见,参数就不改变了,就改变type,实际上是不同的type,参数也会不相同
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
J2tD6bS-1715037083004)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!