前言

本文为datawhale2022年12月组队学习《大话设计模式》task2打卡学习,内容主要以官方所提供为主,会加入一些个人的学习心得。
【教程地址】https://github.com/datawhalechina/sweetalk-design-pattern

一、策略模式

1.1 基本定义

策略模式(Strategy Pattern)是指定义一个算法家族,使得家族内的不同算法都遵从算法家族的接口及方法规范,从而可以实现算法间互相替换,且不会影响到使用算法的客户。
简单来说,就是提前准备好一组算法,将每一个算法的实现封装起来,在使用时进行互换。

1.2 问题引入

实现一个商场收银软件程序,营业员可以通过输入客户所有购买商品的单价和数量,程序自动计算出总金额。同时,商场有时会有打折活动(如商品打7折),或满减促销活动(如商品满300-100),程序应能考虑这些活动的情形,在尽量减少重复代码的前提下,实现正确的金额计算。

1.2.1 问题分析

对于打7折,打8折,满300-100,满700-200等商场的促销活动,其整体的业务逻辑是类似的,而且随时可以相互替换,符合策略模式的应用场景。

1.2.2 问题解决

  1. 首先创建抽象的算法类CashSupur,作为所有促销活动算法的抽象类,同时定义所有支持算法的公共接口,定义方法acceptCash()用于得到结果;
  2. 创建具体的促销算法类CashNormalCashRebate等,继承于抽象算法类CashSupur,覆写acceptCash()实现具体的促销算法;
  3. 创建上下文类CashContext,维护对算法对象的引用,使用时根据用户输入,传入一个具体的促销算法类来配置。

1.2.3 代码实现

这里不再多余进行复制粘贴了,直接放上datawhale所给的的源码链接:
策略模式Java实现
策略模式python实现

1.3 与简单工厂模式的区别

其实单看代码,直观给人感觉高度相似,没有什么区别,但是如果深入分析一下,其实还是有许多不同。

  • 首先看这两种模式的实现类:

简单工厂模式 :

# 简单工厂方法实现
class CashFactory(object):def create_cash_accept(self,typ):cs = CashSuper()if typ == "正常收费":cs = CashNormal()elif typ == "满300返100":cs = CashReturn()cs.cash_return("300","100")elif typ == "打8折":cs = CashRebate()cs.cash_rebate("0.8")return cs

策略模式 :

# 策略模式上下文类实现
class CashContext(object):def __init__(self,typ):self.cs = CashSuper()if typ == "正常收费":self.cs = CashNormal()elif typ == "满300返100":self.cs = CashReturn()self.cs.cash_return("300","100")elif typ == "打8折":self.cs = CashRebate()self.cs.cash_rebate("0.8")def get_result(self,money):return self.cs.accept_cash(money)
  • 再来看后面的调用:

简单工厂模式 :

csuper = CashFactory().create_cash_accept(self.comboVar.get())
totalPrice = csuper.accept_cash(float(self.txtPrice.get()) * float(self.txtNum.get()))

策略模式 :

csuper = CashContext(self.comboVar.get())
totalPrice = csuper.get_result(float(self.txtPrice.get()) * float(self.txtNum.get()))

从代码中可以看到:
工厂模式主要是返回的接口实现类的实例化对象,最后返回的结果是接口实现类中的方法,而策略模式是在实例化的过程中将策略一并创建完。
对于不同的业务,策略模式需要在上下文类中实现,而工厂模式则是需要实例化后再对不同的功能进行拼接。
相对来说,策略模式注重的是过程,而工厂模式只关注最后的结果。

二、装饰模式

2.1 基本定义

装饰模式(Decorator Pattern)是指创建一个装饰类,来包装原有的类,从而实现动态地向一个现有的对象添加一些额外的职责,同时不改变其原有的结构。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

2.2 问题引入

实现人的自由穿搭,要求避免穿每一件衣服的过程直接在客户端实现,同时又保留服装搭配的灵活性。

2.2.1 问题分析

对于人的穿搭问题,衣服、鞋子、领带、披风等服饰都可以理解为对人的装饰。可以先定义一个Person类表示人,然后再定义具体的服饰类实现对Person类进行服装装饰,装扮完再统一显示

2.2.2 问题解决

  1. 创建抽象的接口类Component,定义给对象动态添加职责的公共接口(在此例中,由于具体的接口只有一个,所以该步也可省略);
  2. 创建具体的接口Person(Concrete Component),继承于抽象接口类Component,同时:
    • 定义方法Show()用于显示装扮结果;
  3. 创建抽象的装饰类Finery(Decorator),继承于接口类Person(一般来说继承于抽象接口类Component,由于此例只有一个接口,故继承于具体接口类),同时:
    • 定义方法Decorate(component)用于进行装扮过程;
    • 覆写Show()具体装扮结果的显示;
  4. 创建系列具体的服饰类(Concrete Decorator),如TshirtsBigTrouser等,继承于抽象装饰类Finery,实现具体的装饰对象,同时:
    • 覆写Show()具体装扮结果的显示。

2.2.3 代码实现

这里依然不再多余进行复制粘贴了,直接源码链接:
装饰模式Java实现
装饰模式python实现

2.3 优缺点

2.3.1 优点

  • 装饰类和被装饰类可以独立发展,而不会相互耦合。它有效地把类的核心职责和装饰功能分开了
  • 装饰模式是继承关系的一个替代方案,无需创建新子类即可实现对类功能的动态扩展
  • 装饰模式可以动态地扩展一个实现类的功能

2.3.2 缺点

  • 各装饰层的代码相对冗余,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像
  • 在封装器栈中删除特定封装器比较困难
  • 较难实现行为不受到先后顺序影响的装饰

三、代理模式

3.1 基本定义

代理模式(Proxy Pattern)是指实现一个类代表另一个类的功能,为其他对象提供一种代理以控制对这个对象的访问。

3.2 问题引入

隔壁班的卓贾易想追求娇娇,但是他自己不好意思,就委托和娇娇同班的戴励帮助他。卓贾易给娇娇先后买了芭比娃娃、花、巧克力,饼委托戴励送给娇娇,却没想给娇娇和戴励创造了相处的机会。娇娇和戴励通过接触互生情愫,最后在一起了。卓贾易自然是很生气,一番追求却为他人做了嫁衣。但细细想来,虽说一直是卓贾易给娇娇买的礼物,但娇娇自始至终都是从戴励手里拿到的礼物,她并未接触过送礼之人——卓贾易。
这真是个悲伤的故事…

3.2.1 问题分析

用程序来描述这一个故事,关键之处在于准确描述卓贾易、戴励及娇娇三者之间的行动关系:娇并不认识卓贾易,礼物是卓贾易买的,戴励并没有礼物直接送给娇娇。
这一问题中有三个类型的角色,追求者(卓贾易),代理(戴励)和被追求者(娇娇)。他们三者间的关系满足,追求者(卓贾易)委托代理(戴励),通过代理(戴励)给被追求者(娇娇)送礼物,而被追求者(娇娇)只与代理(戴励)有接触。
若使用代理模式描述,即代理(戴励)代表了追求者(卓贾易)的追求(赠送礼物)的功能,被追求者(娇娇)仅与代理(戴励)接触便收到了礼物。这样就实现了他们三人关系的准确描述。

3.2.2 问题解决

  1. 创建送礼物的抽象类IGiveGift,定义追求者和代理的共用接口:

    • 送玩具方法GiveDolls();
    • 送花方法GiveFlowers();
    • 送巧克力方法GiveChocolate()
  2. 创建追求者Pursuit,定义需要代理的真正实体,继承于抽象类IGiveGift:
    • 覆写类初始化方法,记录被追求者姓名;
    • 覆写送玩具、送花、送巧克力方法,具体送礼操作。
  3. 创建代理Proxy,保存追求者实体的一个引用,使得代理可以访问实体,继承于抽象类IGiveGift,实现对实体的替代:
    • 覆写类初始化方法,初始化的同时初始化一个追求者Pursuit对象;
    • 覆写送玩具、送花、送巧克力方法,在每一个送礼方法下调用追求者Pursuit的具体送礼操作。

3.2.3 代码实现

源码链接:
代理模式Java实现
代理模式python实现

3.3 优缺点

3.3.1 优点

  • 引入代理后,职责清晰;
  • 引入代理后,可扩展多种用途,如:
    • 远程代理可以隐藏一个对象存在于不同地址空间的事实。
    • 虚拟代理可以存放实例化时间很长的真实对象。
  • 符合“开放封闭原则”,无需对服务器或客户端进行修改就创建新的代理。

3.3.2 缺点

  • 实现代理模式需要额外的工作(有些代理模式的实现非常复杂),代码可能变得复杂;
  • 由于在客户与真实目标之间增加了代理对象,因此会造成请求的处理速度变慢,服务响应可能产生会延迟。

参考

[1] datawhale大话设计模式教程云 - GitHub
[2] 个人理解简单工厂模式和策略模式的区别
[3] 设计模式——装饰模式(Decorator)
[4] 10分钟看懂动态代理设计模式

设计模式-策略、装饰、代理相关推荐

  1. Java设计模式(装饰者模式-组合模式-外观模式-享元模式)

    Java设计模式Ⅳ 1.装饰者模式 1.1 装饰者模式概述 1.2 代码理解 2.组合模式 2.1 组合模式概述 2.2 代码理解 3.外观模式 3.1 外观模式概述 3.2 代码理解 4.享元模式 ...

  2. 【设计模式】装饰者模式 ( 概念 | 适用场景 | 优缺点 | 与继承对比 | 定义流程 | 运行机制 | 案例分析 )

    文章目录 I . 装饰者模式概念 II . 装饰者模式适用场景 III . 装饰者模式优缺点 IV . 装饰者模式与继承对比 V . 装饰者模式相关设计模式 VI . 装饰者模式四个相关类 VII . ...

  3. 15. 星际争霸之php设计模式--策略模式

    题记 ============================================================================== 本php设计模式专辑来源于博客(jy ...

  4. 详解设计模式:装饰器模式

    装饰器模式(Decorator Pattern)也称为包装模式(Wrapper Pattern),是 GoF 的 23 种设计模式中的一种结构型设计模式.装饰器模式 是指在不改变原有对象的基础之上,将 ...

  5. 设计模式之装饰者模式--钢铁侠的形成

    前言 本文主要讲述java常见设计模式之装饰者模式,文中使用通俗易懂的案例,使你更好的学习本章知识点并理解原理,做到有道无术. 一.什么是装饰者模式 装饰者模式是23种设计模式中结构型模式的一种,它的 ...

  6. 设计模式之装饰者模式(五)

    设计模式之装饰者模式(五) 前几天把创建型设计模式学习了一下,因为之前了解过,算是复习吧. 接下来进行结构型设计模式,结构型设计模式包括:适配器,桥接,外观,组合,装饰者,享元,代理 今天来学习装饰者 ...

  7. Python设计模式-策略模式

    Python设计模式-策略模式 代码基于3.5.2,代码如下; #coding:utf-8 #策略模式class sendInterface():def send(self,value):raise ...

  8. 前端也要学系列:设计模式之装饰者模式

    什么是装饰者模式 今天我们来讲另外一个非常实用的设计模式:装饰者模式.这个名字听上去有些莫名其妙,不着急,我们先来记住它的一个别名:包装器模式. 我们记着这两个名字来开始今天的文章. 首先还是上< ...

  9. 设计模式 之 装饰者模式

    2019独角兽企业重金招聘Python工程师标准>>> 设计模式 之 装饰者模式 装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对 ...

  10. 设计模式学习----装饰器模式

    这两天本来是自在学习java collection Framework的Fail Fast底层机制,看到核心的部分时,突然意识到设计模式的问题,上大学到现在我还没有真正理解过设计模式的概念,于是用了大 ...

最新文章

  1. 深度学习框架大战,我该选哪个?
  2. linux主节点启动nfs,51CTO博客-专业IT技术博客创作平台-技术成就梦想
  3. 为什么需要批判性思维 -- 读《学会提问》
  4. 有名管道(FIFO)实现无亲缘关系的客户服务器
  5. 绝了!这款工具让 SpringBoot 不再需要Controller、Service、DAO、Mapper!
  6. 数据科学真的是一份有前途的工作吗?
  7. 步骤6 - WebSocket服务器把请求的响应结果推送给webshop
  8. zookeeper 日志查看_每天使用的注册中心zookeeper,流量暴涨怎么办?
  9. php实现tcp连接的原理,PHP实现TCP实例
  10. Jquery的ajax 三级联动 03
  11. mysql引擎机制_MySQL引擎特性:InnoDB同步机制
  12. java rbac 开源_java web快速开源开发框架RoubSite-admin
  13. mysql的底层运行原理,【数据库】震惊!!MySQL的底层原理竟然是这样
  14. 使用 CloudFlare CDN 自定义节点加速网站
  15. 三星固态驱动安装失败_三星SSD无法安装Win10无法启动解决方案
  16. office图标异常处理
  17. 摄像头 RTSP 以及远程管理
  18. 结构化数据、半结构化数据和非结构化数据分析
  19. javascript判断浏览器和终端类型,js如何区分手机、电脑终端和浏览器
  20. [刷题]剑指offer C++语言刷题-多解法尝试

热门文章

  1. OS Command 调用 ODI Senario
  2. 高仿百科资料php,高仿喵喵折前端代码
  3. 一文带你彻底拿下a,b两点间等效电阻
  4. redis缓存雪崩、击穿、穿透
  5. 支付宝支付设计和开发方案
  6. js读取解析JSON数据(转)
  7. node.js 如何读取json文件内容
  8. 百度地图_自动标记/点击图标显示对应信息
  9. python+monkey+ 监控 crash,性能统计
  10. 我的世界服务器动物怎么无线繁衍,我的世界圈养动物让它们繁殖 教程分享