设计模式V1.0版
2021-09-05 11:35:13 0 举报
AI智能生成
23种设计模式,一张图从总体上了解设计模式。结合记忆法,容易记忆
作者其他创作
大纲/内容
七大原则
单一职责
降低类的复杂度
提高类的可维护性、可读性
降低变更带来的风险
接口隔离原则
客户端不应该依赖它不需要的接口
一个类对另一个类的依赖应该建立在最小的接口上
依赖倒置原则
高层模块不能依赖低层模块,二者都依赖于抽象
抽象不应该依赖细节,细节依赖抽象
里氏替换原则
开闭原则
迪米特法则
知道最少原则
一个对象应该对其他对象知道的越少越好
组合原则
组合是实心菱形,需要实例化
概括图
创建型
1.单例模式
快速记忆:千年古树孤单的倒立在黑暗的古刹上,吓死人了
概念
剖析原理
保证在内存中只有一个实例
指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。
结构
用例图
分类
1、饿汉式
2、懒汉式
不加锁
加一个锁
双重检查
3、静态内部类
4、枚举
应用场景
生活场景
源码场景
优缺点
优点
单例模式可以保证内存里只有一个实例,减少了内存的开销
可以避免对资源的多重占用
单例模式设置全局访问点,可以优化和共享资源的访问
缺点
单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。
在并发测试中,单例模式不利于代码调试。在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。
单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。
2.工厂方法
快速记忆:唐老鸭熬白了头发思虑经营工厂的方法
概念
是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则
结构
用例图
角色
抽象工厂
具体工厂
抽象产品
具体产品
分类
应用场景
生活场景
农场:养马场、养牛场
源码场景
优缺点
优点
用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程
灵活性增强,对于新产品的创建,只需多写一个相应的工厂类
典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则
缺点
类的个数容易过多,增加复杂度
增加了系统的抽象性和理解难度
抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决
2.1 简单工厂(静态工厂)-非23设计模式之一
概念
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点
结构
用例图
角色
简单工厂
抽象产品
具体产品
场景
对于产品种类相对较少的情况,考虑使用简单工厂模式
优缺点
优点
工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。
客户端无需知道所创建具体产品的类名,只需知道参数即可
也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类
缺点
简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则
使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。
3.抽象工厂
快速记忆:耳朵流着红红的鲜血的大象,横冲直撞踩碎了豪华的大工厂
概念
是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
条件
系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品
系统一次只可能消费其中某一族产品,即同族的产品一起使用
结构
用例图
角色
抽象工厂
具体工厂
抽象产品
具体产品
应用场景
生活场景
源码场景
理论
当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等
系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构
优缺点
优点
可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理
当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品组。
抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则
4.原型模式
快速记忆:按照轮船的原型,复制轮船舰队
概念
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象
结构
用例图
角色
抽象原型类
具体原型类
访问者
分类
浅克隆
创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址
深克隆
创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
基于序列化的方式实现
基于clone的方式实现
应用场景
生活场景
游戏怪物
源码场景
优缺点
5.建造者模式
快速记忆:五指山下建造一座臭烘烘的小茅房,苍蝇漫天飞
概念
指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
结构
用例图
角色
产品角色
抽象建造者
具体建造者
指挥者
分类
应用场景
生活场景
装修
施工图:product
工人-Builder
包工头=Director
源码场景
String Builder
优缺点
优点
封装性好,构建和表示分离。
扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险
缺点
产品的组成部分必须相同,这限制了其使用范围
如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大
结构性
6.代理模式
快速记忆: 樱桃代理商黑心的把长毛的樱桃卖给老百姓
概念
由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
结构
用例图
角色
抽象主题类,目标对象的接口
具体主题类,目标对象
代理对象Proxy
分类
静态代理
动态代理
2、1 jdk实现方式
采用组合来实现
2.2 CGLIb
是一个高性能的代码生成包,在内存中动态生成
为没有接口的类实现代理,也可以为定义了接口的类实现代理
采用继承来实现
不能为生成final 的类生成代理类
步骤
1.Enhancer 对象
2、设置父类
3、设置回调函数
4、继承MethodInterceptor ,实现回调函数
2.3 asm 字节码 生成框架
动态生成类 或者增强现有类
使用场景
生活
远程代理
防火墙代理
保护代理
源码
AOP
优缺点
优点
保护被代理对象
扩展被代理对象功能
代理类和目标对象分离
解耦
缺点
增加类的数量
速度
增加系统的复杂度
7.装饰器模式
快速记忆: 镰刀闪着目露凶光,割碎了快餐店的装饰
概念
指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
结构
用例图
角色
抽象构件
具体构件
抽象装饰器
具体装饰器
分类
使用场景
生活
源码
理论
当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时
当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰器模式却很好实现
当对象的功能要求可以动态地添加,也可以再动态地撤销时
优缺点
优点
装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
装饰器模式完全遵守开闭原则
8.适配器模式
快速记忆: 两只葫芦亲嘴,大嘴葫芦借助吸管适配小嘴的葫芦
概念
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
结构
用例图
角色
被适配者 Adaptee
目标:Target
适配器类
分类
类适配器
继承 目标类
对象适配器
组合或者聚合:被适配者类
使用场景
生活
开关转换
源码
理论
以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致
使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。
优缺点
优点
客户端通过适配器可以透明地调用目标接口
复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类
将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题
在很多业务场景中符合开闭原则
缺点
适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性
增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱
9.桥接模式
快速记忆: 千万只猫,搭肩勾背把断桥接起来
概念
将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
结构
用例图
角色
抽象化角色
扩展化角色
实现化角色
具体实现化角色
分类
使用场景
生活
源码
理论
当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时
当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时
当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时
优缺点
优点
抽象与实现分离,扩展能力强
符合开闭原则
符合合成复用原则
其实现细节对客户透明
缺点
由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。
10.外观模式
快速记忆: 十字架 外观金光闪闪的,亮瞎人的眼睛
概念
又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性
结构
用例图
角色
外观角色
子系统角色
客户角色
分类
使用场景
生活
源码
优缺点
优点
对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易
降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类
降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程,因为编译一个子系统不会影响其他的子系统,也不会影响外观对象
典型的迪米特法则
缺点
不能很好地限制客户使用子系统类,很容易带来未知风险
增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”
11.享元模式
快速记忆:筷子在大山里享受着丰裕的元气,走火入魔死掉了
概念
运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
结构
用例图
角色
抽象享元角色
具体享元
非享元
享元工厂
分类
单纯享元模式
都可以共享
复合享元模式
共存
使用场景
生活
俄罗斯方块
围棋:黑白子
源码
理论
大部分的对象可以按照内部状态进行分组,且可将不同部分外部化,这样每一个组只需保存一个内部状态
系统中存在大量相同或相似的对象,这些对象耗费大量的内存资源
由于享元模式需要额外维护一个保存享元的数据结构,所以应当在有足够多的享元实例时才值得使用享元模式
优缺点
优点
相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力
缺点
为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性
读取享元模式的外部状态会使得运行时间稍微变长。
12.组合模式
快速记忆:金黄的银耳组合成一圈,围住了组织机构树
概念
有时又叫作整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式
结构
用例图
角色
抽象构件
树枝构件
树叶构件
分类
透明组合模式
所有组件都有共同的操作
安全组合模式
抽象类中不定义任何方法,在Menu类中生成方法
使用场景
生活
组织机构
源码
树
理论
在需要表示一个对象整体与部分的层次结构的场合
要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合
优缺点
优点
组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码
更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”
缺点
设计较复杂,客户端需要花更多时间理清类之间的层次关系
不容易限制容器中的构件
不容易用继承的方法来增加构件的新功能
行为型
13.模板方法
快速记忆:医生用模板克隆出相同的🐏
概念
特点:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。
结构
用例图
角色
抽象类/抽象模板
具体子类/实现类
分类
使用场景
生活
办理流程
源码
原则
算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现
通过钩子方法控制父类
优缺点
优点
它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展
它在父类中提取了公共的部分代码,便于代码复用
部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则
缺点
对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,间接地增加了系统实现的复杂度
父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍。
14、策略模式
快速记忆:一群钥匙思考策略打开那把锈迹斑斑的锁
概念
当实现某一个功能存在多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能,如数据排序策略有冒泡排序、选择排序、插入排序、二叉树排序等。
该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
结构
用例图
角色
抽象策略类
具体策略类
环境类
分类
使用场景
生活
源码
sort
优缺点
优点
多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句
策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码
策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的
策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法
策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离
缺点
客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类
策略模式造成很多的策略类,增加维护难度
15、命令模式
快速记忆:鹦鹉学舍下命令,让厨师给它做菜
概念
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
结构
角色
抽象命令类
具体命令类
实现者/接收者【厨师】
调用者\请求者【服务员】
用例图
分类
使用场景
生活
客户-点餐-服务员-厨师
源码
优缺点
优点
引入中间件,降低耦合性
满足开闭,扩展良好,增加和删除命令方便
和组合模式实现宏命令
和备忘录结合实现unduo\redo
缺点
产生大量的命令类,增加系统复杂度
引入额外结构,增加理解上的困难
16、责任链
快速记忆:石榴连成一链,各人按照个人的责任干活
概念
为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止
结构
用例图
角色
抽象处理者
具体处理者
客户类
分类
纯的职责链模式
一个请求必须被某一个处理者对象所接收,且一个具体处理者对某个请求的处理只能采用以下两种行为之一:自己处理(承担责任);把责任推给下家处理
不纯的职责链模式
允许出现某一个具体处理者对象在承担了请求的一部分责任后又将剩余的责任传给下家的情况,且一个请求可以最终不被任何接收端对象所接收
使用场景
生活
审批流
源码
过滤器
理论
多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定
可动态指定一组对象处理请求,或添加新的处理者
需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求
优缺点
优点
降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息
增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则
增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任
责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则
缺点
不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理
对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响
职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用
17、状态模式
快速记忆:玉玺生病状态不太好,忽明忽暗的闪着光
概念
对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
结构
用例图
角色
环境类
抽象状态
具体状态
分类
使用场景
生活
线程状态
源码
理论
当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式
一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时
优缺点
优点
结构清晰,状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”。
将状态转换显示化,减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
状态类职责明确,有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。
缺点
状态模式的使用必然会增加系统的类与对象的个数
状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱
状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码
18.观察者模式
快速记忆:饥肠辘辘的18罗汉仔细观察香客,试图找到妖怪煮汤吃了
概念
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
结构
用例图
角色类
抽象主题角色
具体主题角色
抽象观察者角色
具体观察者角色
分类
静态代理
使用场景
生活
源码
事件监听
mq
理论
对象间存在一对多关系,一个对象的状态发生改变会影响其他对象
当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用
实现类似广播机制的功能,不需要知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收该广播。
多层级嵌套使用,形成一种链式触发机制,使得事件具备跨域(跨越两种观察者类型)通知
优缺点
优点
降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则
目标与观察者之间建立了一套触发机制
缺点
当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用
19.中介者
快速记忆:泥鳅挤破了中介所,砰,买房的卖房的全被炸伤了,血流成河
概念
定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用
结构
用例图
角色
抽象中介者
具体中介者
抽象同事类
具体同事类
分类
使用场景
生活
房屋中介
联合国
招聘网站?
媒婆
源码
理论
当对象之间存在复杂的网状结构关系而导致依赖关系混乱且难以复用时。
当想创建一个运行于多个类之间的对象,又不想生成新的子类时
优缺点
优点
类之间各司其职,符合迪米特法则
降低了对象之间的耦合性,使得对象易于独立地被复用
将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展
缺点
中介者模式将原本多个对象直接的相互依赖变成了中介者和多个同事类的依赖关系。当同事类越多时,中介者就会越臃肿,变得复杂且难以维护
20.迭代器
快速记忆:红塔山香烟迭代更替了好几代了
概念
提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示
结构
用例图
角色
抽象聚合类(list)
具体聚合类(ArrayList)
抽象迭代器(iterator)
具体迭代器
分类
使用场景
生活
源码
ArrayList set
理论
当需要为聚合对象提供多种遍历方式时
当需要为遍历不同的聚合结构提供一个统一的接口时
当访问一个聚合对象的内容而无须暴露其内部细节的表示时
优缺点
优点
访问一个聚合对象的内容而无须暴露它的内部表示
遍历任务交由迭代器完成,这简化了聚合类
它支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历
增加新的聚合类和迭代器类都很方便,无须修改原有代码
封装性良好,为遍历不同的聚合结构提供一个统一的接口
缺点
增加了类的个数,这在一定程度上增加了系统的复杂性
21.访问者
动物园鳄鱼发疯撕碎了访问者
概念
将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。
动态分派
重写
静态分派
重载
双分派
重载+重写
结构
用例图
角色
抽象访问者
具体访问者
抽象元素
具体元素
对象结构
分类
使用场景
生活
宠物喂食
源码
优缺点
优点
扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。
灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。
缺点
增加新的元素类很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。
破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。
违反了依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类。
22.备忘录
快速记忆:鸳鸯的新婚之夜,写到了备忘录上
概念
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式
结构
用例图
角色
发起人
备忘录
管理者
分类
使用场景
生活
源码
理论
需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能
需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,Eclipse 等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作
优缺点
优点
提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态
实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息
简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则
缺点
资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源
23. 解释器
快速记忆:乔丹愤怒的解释他没违规
概念
给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。也就是说,用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。
结构
用例图
角色
抽象表达式
终结符表达式
非终结符表达式
环境
客户
概念
::= 该符号的意思是定义为
终结符
非终结符
抽象语法树
分类
静态代理
使用场景
生活
源码
公式解析
优缺点
优点
扩展性好。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法
容易实现。在语法树中的每个表达式节点类都是相似的,所以实现其文法较为容易。
缺点
执行效率较低。解释器模式中通常使用大量的循环和递归调用,当要解释的句子较复杂时,其运行速度很慢,且代码的调试过程也比较麻烦。
会引起类膨胀。解释器模式中的每条规则至少需要定义一个类,当包含的文法规则很多时,类的个数将急剧增加,导致系统难以管理与维护
可应用的场景比较少。在软件开发中,需要定义语言文法的应用实例非常少,所以这种模式很少被使用到
0 条评论
下一页