Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【设计模式】汉堡中的设计模式——策略模式

【设计模式】汉堡中的设计模式——策略模式

作者头像
落寞的鱼丶
发布于 2022-02-26 12:05:30
发布于 2022-02-26 12:05:30
87200
代码可运行
举报
文章被收录于专栏:afjhahfhahajkafjhahfhahajk
运行总次数:0
代码可运行

目录

每章一句

Yesterday home runs don't win today games

前言

哈喽,大家好,今天要分享的知识点是关于策略模式的使用,观看本文章可能需要耗费【8】分钟,通过本文,你可以认识到以下几个知识点

  • 什么是策略模式
  • 针对策略模式的局限,又有哪些解决办法
  • 枚举策略了解一下?

情景带入

话说昨天,麦当劳搞活动,板烧只要5块大洋!!!下班了之后我就骑着心爱的小摩托飞奔过去,在等待了一段(long)时(long)间(time)...... 终于如愿以偿的握着这简单的快乐

看着手里的板烧,心里突然就有了一些想法,现在搞活动,部分商品低价就可以拿到,但是搞活动不能一直搞吧,那不然肯定亏大本了,活动形式也总不能一成不变吧,需要保持新颖,多元化吸引顾客消费

那么变化点就出来了,这个形式是可以不断变化的,例如会有这么几种

  • 打折活动的时候,只需要5块大洋就能拿下一个汉堡
  • 买一送一活动的时候,原价可以拿到两个
  • 优惠券活动,有的时候是有一些优惠券的,达到门槛减多少
  • 没有活动时,需要原价购买

我们常说要透过现象看本质,尽管形式很多,但是万变不离其中,最终是要付钱产生价值的,那就来分析一下这个流程吧!

开始分析

我们再来模拟一下,顾客在各种形式下是怎么点餐的

  • 没有活动时,我把汉堡添加到购物车,创建订单,支付,等待出餐
  • 搞打折活动时,汉堡只需要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(客户端)在接收到方法的时候,最基础时要这么来判断

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//伪代码,暂不校验字段有效性问题

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,参数也会不相同

  1. type为1,原价方式
  1. type为2,优惠券满减策略
  1. type为3,折扣策略
  1. type为4,买一送一策略
  1. type为5,免费送策略

通过简单工厂+策略模式,我们把原本存在于客户端中的判断给挪到工厂里面,把所有的运行逻辑都隐藏起来了;每次有新的策略,只需要新建一个类,修改一下HandlerFactory中的selectStrategy方法即可

不过这也导致了HandlerFactory这个类违背了OCP原则,但是相对于一大段的if-else直接暴露再客户端,这种方法无疑是值得考虑的

枚举策略方式

或许在看完【简单工厂+策略模式】之后小伙伴会有所疑问,这不就是把客户端的判断逻辑给转移到工厂中而已,虽然对于客户端来说,会更加的清爽,可是似乎没有根本性的解决问题,工厂中把if-else换成了switch-case,新的策略该创建类还是要创建类,所以该膨胀还是得膨胀啊。。。

那没办法了,只能出绝招了,

使用枚举策略模式,相当于策略来说,枚举策略更像是他的改良升级版本,使用起来也更加的灵活,不需要创建大量的类来充当各个具体实现,也不需要满屏幕的if-else或者switch-case,看起来就相当的诱人

枚举大家都使用过,常用来定义一些常量信息,而枚举策略就是在枚举类里边加上抽象方法,让每个常量都实现这些方法

例如,我在枚举里边定义这两个方法

那么我的每一个枚举成员都必须实现这两个方法

给出完整的代码

客户端调用情况

可以发现,原本各个实现类都不需要了,只需要在枚举中定义成员,即可达成原来的效果,而且在匹配对应的策略时,直接使用循环的方式,看起来非常的清爽

如果要添加新的策略,直接在枚举里边添加成员,实现对应的方法即可,而且将所有的策略统一管理起来,方便维护

唯一的缺点,可能就是策略越来越多的时候,这个枚举类也会越来越长,但是通过成员来管理,注释写好,也不会显示很混乱

总结

所以,策略模式到底是什么?

就是提供很多很多的算法,让客户端可以动态的选择使用哪一个,其实在MVC中,View通过url把请求给到Controller处理,就是一种典型的策略选择,View可以随时更换url,绑定给另外一个Controller处理

事务都有两面性,所以针对策略模式的局限,我们需要做额外的工作,把不好的影响降到我们能接受的度

好啦,本期文章就到这里了,限于本人水平的问题,如果有说得不对的地方,欢迎指出!我们下期再见!

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
设计模式之 - 策略落实
策略模式:它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式的变化,不会影响到使用算法的客户。
一个程序员的成长
2020/11/25
3570
设计模式之 - 策略落实
【经典案例】Python详解设计模式:策略模式
比如,超市做活动,如果你的购物积分满1000,就可以按兑换现金抵用券10元,如果购买同一商品满10件,就可以打9折,如果如果购买的金额超过500,就可以享受满减50元的优惠。这是三个不同的促销策略。
一墨编程学习
2019/05/10
8840
【经典案例】Python详解设计模式:策略模式
Java设计模式-策略模式
Java设计模式-策略模式,一起来看看吧,让我们一起为进阶做一个充足的准备吧!!!! 会了就当复习丫,不会来一起来看看吧。 很喜欢一句话:“八小时内谋生活,八小时外谋发展”。 如果你也喜欢,让我们一起坚持吧!! 共勉😁 我想这才是夏天吧,心目中的夏天 一、前言 1)引入: 在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,今天的作业该让这个女朋友写还是那个女朋友写勒?好难选啊,算了吧还是自己来吧。(其实就是没有😂)。正文:例如,出行旅游可以乘坐飞机、乘坐火车、骑自行车或
宁在春
2022/10/31
4340
Java设计模式-策略模式
设计模式之策略模式
策略模式(Strategy Pattern)隶属于设计模式中的行为型模式,是日常开发中使用最广的一个模式,相对于其他模式,自认为这个模式是最容易理解和使用的。
Dylan Liu
2019/08/22
6350
重学 Java 设计模式:实战策略模式「模拟多种营销类型优惠券,折扣金额计算策略场景」
作者:小傅哥 目录 一、前言 二、开发环境 三、策略模式介绍 四、案例场景模拟 五、用一坨坨代码实现 1. 工程结构 2. 代码实现 六、策略模式重构代码 1. 工程结构 2. 代码实现 3. 测试
小傅哥
2020/07/10
2.8K0
重学 Java 设计模式:实战策略模式「模拟多种营销类型优惠券,折扣金额计算策略场景」
『设计模式』设计模式--策略模式
今天去超市买东西,买了50多块钱的东西,然后收钱的时候他多收了,明明会员要打白金会员打9折,黄金会员95折,我是白金会员因该是9折。 我问她:“你是不是不知道什么是策略模式” 她一脸茫然地看着我,“啊?先生请您再说一遍。” 我说:“我是白金会员,请选择白金会员的策略” 她说:“不好意思,您一年没来我们这里买过东西了,已经给您降档了!” 我说:“还有这操作?。。。。” 朋友觉得我为了几块钱这么墨迹,付完钱拉着我就走了,问我:“你说的什么模式怎么回事?” 我说超市收银系统就是很好的策略系统,就是一个典型策略模式。 多收了2块5,心疼死我了,我慢慢给你讲!
风骨散人Chiam
2020/10/28
2.1K1
《大话设计模式》解读02-策略模式
本篇文章,来解读《大话设计模式》的第2章——策略模式。并通过Qt和C++代码实现实例代码的功能。
xxpcb
2024/06/16
1020
《大话设计模式》解读02-策略模式
设计模式专题(二)——策略模式
设计模式专题(二)——策略模式 (原创内容,转载请注明来源,谢谢) 一、概述 1、含义 策略模式(Strategy)是一种定义了各类算法的模式,其将各种算法分别封装起来,在需要的时候去拉取各种算法,但并不影响使用算法的客户,实现让算法和对象分开来,使得算法可以独立于使用它的客户而变化。当执行某件事时,各类算法都可能用到,且变化性比较大,就适用于策略模式。 2、基本规则 1)策略模式定义的各种算法应该是完成同样的一件事,但是允许输入的内容不同,返回的结果也可以不同。 例如商场的营销策略,
用户1327360
2018/03/07
7940
设计模式专题(二)——策略模式
设计模式—–策略模式
**策略这个词应该怎么理解,打个比方说,我们出门的时候会选择不同的出行方式,比如骑自行车、坐公交、坐火车、坐飞机、坐火箭等等,这些出行方式,每一种都是一个策略 **
对弈
2019/11/02
5210
设计模式(十四):行为型之策略模式
冬天vs不冷
2025/01/21
1060
设计模式(十四):行为型之策略模式
从零开始单排学设计模式「策略模式」黑铁 II
设计模式不是语法,是一种巧妙的写法,能把程序变的更加灵活。架构模式比设计模式大,架构模式是战略,而设计模式是战术。
良月柒
2019/03/20
3470
从零开始单排学设计模式「策略模式」黑铁 II
【设计模式】策略模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
策略模式 : 定义了 算法家族 , 分别 封装起来 , 让它们之间 , 可以 相互替换 , 此模式 让 算法的变化 不会影响到 使用算法的用户 ;
韩曙亮
2023/03/29
1.1K0
23种设计模式(二)---策略设计模式
策略设计模式---透彻讲解 一. 什么是策略设计模式 设计模式有三种:创建型, 行为型, 结构型. 策略设计模式属于行为型. 为什么属于行为型呢? 来看看下面解释: 1.1 什么是策略呢? 什
用户7798898
2021/06/23
5850
23种设计模式(二)---策略设计模式
三分钟理解“策略模式”——设计模式轻松掌握
实际问题: 由于超市隔三差五就要办促销活动,但每次促销活动的方式不一样,所以需要开发一个软件,营业员只要输入原价再选择活动类型后,就能计算出折扣以后的价钱。 普通人的做法: mian(){ String input = readLine(); double price = readLine(); switch (input) case "九五折": price = price * 0.95; break; case "满100返50": if(price>=100) pri
大闲人柴毛毛
2018/03/09
7880
三分钟理解“策略模式”——设计模式轻松掌握
重生之设计模式:策略模式
在软件开发中,我们常常会遇到这样的场景:​同一个功能需要根据不同的条件选择不同的算法或行为。例如:
HandsomeYo
2025/04/03
640
重生之设计模式:策略模式
Java设计模式-策略模式
策略模式: 定义一系列的算法, 将其一个个封装起来, 并使它们可相互替换, 使得算法可独立于使用它的客户而变化. (图片来源: 设计模式: 可复用面向对象软件的基础) 策略模式对应于解决某一问题的
Java帮帮
2018/03/16
9380
Java设计模式-策略模式
商业鬼才教你 策略模式
于是,广告一发,横幅一拉,喇叭一吹,开业大吉,生意红火,广军赚到了人气,学生们吃的也很开心。
看、未来
2020/09/18
4760
商业鬼才教你 策略模式
策略模式——(+简单工厂模式+反射)
策略模式,需要我们结合简单工厂模式,更高级地用法可能需要我们掌握Java反射机制。简单工厂模式我们在最早的时候介绍,我们也谈到了一点Java的反射机制。借着学习策略模式的机会,我们顺便复习一下简单工厂模式和反射。 先说说何为策略模式。“策略”我的理解是,对一件事,有不同的方法去做,至于用何种方法取决于我们的选择。我们同样借助《大话设计模式》中实现策略模式的例子来做讲解。 超市进场做活动,我们现在假设有正常不减价、打折、满减这三种活动,这正是对“买东西收费”这件事,有三种不同的“方法”,这三种方法其实就是三种
用户1148394
2018/01/09
1.7K0
策略模式——(+简单工厂模式+反射)
大话设计模式--第二章 策略设计模式
现在有一个需求: 给商场做一个收银软件. 营业员根据客户购买的产品的单价和数量, 向客户打印小票。
用户7798898
2020/09/27
1.4K0
大话设计模式--第二章 策略设计模式
设计模式学习之路一:策略模式
小弟最近在研究设计模式,准备边学边发博客,与众多大佬们交流学习,希望各位能够指出不足之处(废话不多说了,直接开花)
止术
2020/09/15
2910
推荐阅读
相关推荐
设计模式之 - 策略落实
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验