设计模式总结
前言
设计模式总结。
面向对象的特性:3点
- 封装
- 继承
- 多态
编程代码的原则/面向对象的优势:4点
- 可维护
- 可复用
- 可扩展
- 可灵活/灵活性好
统一建模语言(UML)图的基本关系:6种
- 继承:实线,三角箭头,指向被继承类
- 实现:虚线,三角箭头,指向被实现接口
- 依赖:虚线,箭头,指向被依赖者
- 关联:实线,箭头,指向被关联者
- 聚合:空心菱形,实线箭头,指向被聚合者
- 组合:实心菱形,实线箭头,指向被组合者
继承和实现关系的区别:
- (抽象)类/继承和接口/实现在一定程度上可相互转换代替
- (抽象)类:抽象类型,对象之间有关系,属于同一类型,使用继承关系。如:雁和鸟,雁是鸟类型
- 接口:抽象行为,对象之间无关系,有共同行为,使用实现关系。如:飞机和鸟,都有飞行的行为
依赖、关联、聚合和组合的区别:
依赖:
- 表现:方法中的形式参数、局部变量和静态方法调用
- 侧重:临时性
关联:
- 表现:方法中的形式参数,类中的成员字段
- 侧重:长期性;对象间是平等的,对象了解对象。如:企鹅了解气候
聚合:
- 表现:类中的成员字段
- 侧重:长期性;对象间是不平等的,对象包含对象;整体和部分的可分割关系。如:雁群和雁
组合:
- 表现:类中创建、删除的对象(管理对象的生命周期)
- 侧重:长期性;对象间是不平等的,对象包含对象;整体和部分的不可分割关系。如:鸟和翅膀
注意:
- 依赖、关联、聚合和组合关系大多依据语义而不是实现进行判断
弱强程度:
- 依赖<关联<聚合<组合
设计模式的原则:7种
开放-封闭/开-闭原则(OCP)
描述:对扩展开放,对修改关闭
应用:可扩展新代码,不可/尽量不修改旧代码
依赖倒转/置原则(DIP):
描述:高层模块不应该依赖低层模块,两种模块都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象(其中的“不应该”和“应该”是“依赖倒转”的体现)
应用:不面向实现编程,面向接口/抽象类编程;使用抽象类/接口作为变量、参数
单一职责原则(SRP):
- 描述:类的逻辑/功能/职责单一;引起类变化的原因应该有且仅有一个
- 应用:拆分业务对象/逻辑/功能/职责
最少知识原则/迪米特法则(LoD)
描述:类间弱耦合;类间间接而不直接通信
应用:尽可能封装类;使用第三者转发类间的调用
里氏代换原则(LSP)
- 描述:子类型必须能够代换其父类型;子类可扩展父类功能,不可修改父类功能
- 本质:面向对象的多态特性
- 应用:使用子类扩展业务逻辑
接口隔离原则(ISP):
- 描述:客户端不应该依赖不需要的接口;类间关系应该建立在最小的接口上
- 应用:依据业务逻辑拆分复杂多用接口为简单专用接口
合成/聚合复用原则(C/ARP)
- 描述:类间尽量使用依赖、关联、聚合和组合关系,尽量不使用继承关系
- 应用:类间尽量使用依赖、关联、聚合和组合关系,尽量不使用继承关系
设计模式原则的关系(记忆方式):
- 总体规则:开放-封闭/开-闭原则(OCP),依赖倒转/置原则(DIP)
- 设计模式的核心是面向对象
- 面向对象的封装:单一职责原则(SRP),最少知识原则/迪米特法则(LoD)
- 面向对象的继承和多态:里氏代换原则(LSP),接口隔离原则(ISP)
- 类间关系的描述——合成复用原则(C/ARP)
设计模式的类型:3种
依据意图:
- 创建型:负责提供创建对象的机制
- 结构型:负责将对象组装成较复杂的结构,同时保持结构的灵活和高效
- 行为型:负责对象间的高效沟通和职责委派
创建型设计模式:6种
单例模式(Singleton):
- 描述:保证一个类仅有一个实例,并提供一个访问它的全局访问点
- 关键实现:单例类有:私有静态单例类对象字段A,私有构造方法B,公有静态获取单例类对象方法C。客户端单例类对象调用C->可能调用B,获得A
- 类型:饿汉式,懒汉式
- 相关内容:线程安全,双重锁定,静态初始化
- 类比: 木星是唯一的,“木星”、“太阳系最大的行星”和“Jupiter”称谓都是指木星
简单工厂模式(Simple Factory):
- 关键实现:客户端调用简单工厂类的静态方法:判断并创建产品类对象
- 相关内容:反射
- 其他:不属于23种GoF设计模式之一。因为违背开放-封闭/开-闭原则(OCP):扩展需要修改简单工厂类:增加产品类对象的判断和创建代码
- 类比: 建造汽车工厂,让汽车工厂生产引擎产品和轮胎产品
工厂方法模式(Factory Method):
- 描述:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类
- 关键实现:客户端判断并创建具体工厂类对象A,A创建具体产品类对象
- 相关内容:反射
- 类比: 建造汽车引擎工厂,让汽车引擎工厂生产引擎产品;建造汽车轮胎工厂,让汽车轮胎工厂生产轮胎产品
抽象工厂模式(Abstract Factory):
- 描述:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
- 关键实现:工厂和产品表现二/多维结构:客户端判断并创建具体工厂类对象A,一个A,可创建多个同系列不同种类的具体产品类对象
- 相关内容:反射,配置文件
- 类比: 建造A品牌汽车工厂,让A品牌汽车工厂生产A品牌引擎产品和A品牌轮胎产品;建造B品牌汽车工厂,让B品牌汽车工厂生产B品牌引擎产品和B品牌轮胎产品(系列/风格/品牌和种类是二维结构)
原型模式(Prototype):
- 描述:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
- 关键实现:客户端原型类对象调用原型类的克隆方法->调用原型类的构造方法:参数接收当前原型类对象A(this),创建并返回A的副本
- 相关内容:浅拷贝和深拷贝
- 类比: 细胞的有丝分裂/克隆
建造者模式(Builder):
- 描述:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
- 关键实现:客户端指挥者类对象调用指挥者类的指挥方法:参数接收具体建造者类对象A(建造过程)->A调用具体建造者类的具体获取产品方法(建造结果)
- 类比: 创建指挥机器(指挥机器封装建造过程的内容和时序:如建造房屋需要建造墙壁和房门,先建造墙壁后建造房门),创建建造机器(建造机器封装产品的各个建造细节:如建造墙壁的方式,建造房门的方式)。让指挥机器建造房屋->指挥机器指挥房屋建造机器建造房门产品和墙壁产品
结构型设计模式:7种
代理模式(Proxy):
- 描述:为其他对象提供一种代理以控制对这个对象的访问
- 关键实现:代理类(代理者)与具体服务类(被代理者)继承/实现相同的抽象服务类/接口。客户端代理类对象调用代理类的方法->具体服务类对象调用具体服务类的方法(代理过程)
- 类比: 信用卡和现金都能支付,使用信用卡代替现金支付
适配器模式(Adapter):
- 描述:将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
- 关键实现:需适配类(被适配者)和目标类(适配者)的接口不同,适配器类(中间者)和目标类(适配者)的接口相同。客户端目标类类型的适配器类对象调用适配器类的方法->需适配类对象调用需适配类的方法(适配过程)
- 类型:类适配器模式,对象适配器模式
- 类比: 电源适配器适配不同的源电压和电器,源电压不同电器依然能正常工作
外观模式(Facade):
- 描述:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
- 关键实现:客户端外观类对象调用外观类的方法(管理者,搭配子系统类方法的调用内容和时序/步骤)->子系统类对象调用子系统类的方法(被管理者)
- 类比: 安装电源总开关并连接电灯电源开关和空调电源开关,关闭电源总开关可关闭电灯电源和空调电源
装饰模式(Decorator):
- 描述:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活
- 关键实现:装饰类(装饰者)和组件类(被装饰者)有相同接口。客户端具体装饰类对象A调用设置方法:参数接收具体组件类对象B(装饰过程),A调用方法->B调用具体组件类的方法(固有内容),执行其他内容(装饰内容)
- 类比: 人类穿衣服,可以选择穿毛衣、夹克或者风衣
组合模式(Composite):
- 描述:将对象组合成树形结构以表示“部分-整体”的层次结构。使得用户对单个对象和组合对象的使用具有一致性
- 关键实现:组合类对象(树根)和叶子类对象(树叶)有相同接口A。客户端组合类对象B(树根)调用添加方法:参数接收组合类对象C(树枝)或叶子类对象D(树叶),A调用方法B->C递归调用B,D调用B
- 相关内容:透明方式,安全方式
- 类比: 军事命令依据军队的层次结构传递:司令->军->师->旅->团->营->连->排->士兵
桥接模式(Bridge):
- 描述:将抽象部分与它的实现部分分离,使它们都可以独立地变化
- 关键实现:客户端抽象抽象类类型的具体抽象类对象A调用设置方法:参数接收抽象实现类类型的具体实现类对象B,A调用具体抽象类方法->B调用具体实现类方法
- 类比: A品牌手机安装(不知道软件的实现细节)A品牌通讯录和A品牌游戏。反之,A品牌手机自带实现(知道软件的实现细节,每品牌手机都要自带实现相关软件)A品牌通讯录和A品牌游戏
享元模式(Flyweight):
- 描述:运用共享技术有效地支持大量大量细粒度的对象
- 关键实现:享元类和不共享类有相同接口A。客户端享元工厂类对象调用方法:参数接收内容(键),查找散列/哈希表,创建、记录并获取或直接获取享元类对象B(值,共享内容/内部状态),B调用方法:参数接收内容(不共享内容/外部状态),执行相关操作。不共享类对象(不共享内容/外部状态)和B实现类似
- 类比: 相似的网站使用同一服务器资源、系统和实例,依据网站所有者的不同显示不同页面
行为型设计模式:11种
模板方法模式(Template Method):
- 描述:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
- 关键实现:客户端抽象类类型的具体类对象调用抽象类的模板方法:定义多个步骤方法的组合内容和执行时序((算法)模板,不变化行为)->调用抽象类的步骤方法->调用具体类的步骤方法(具体步骤实现,变化行为)(面向对象的多态特性)
- 类比: 房屋建造的步骤和时序固定:先打地基,后建墙壁,打地基的方式,墙壁类型的选择不固定
策略模式(Strategy):
- 描述:定义了算法家族,分别封装起来,让它们之间可以互相替换,让算法的变化,不会影响到使用算法的客户
- 关键实现:客户端上下文类对象调用上下文类的方法->抽象策略类类型的具体策略类对象调用具体策略类的方法(多态特性,同系列不同类型算法)
- 相关内容:在上下文类中使用简单工厂模式判断并创建抽象策略类类型的具体策略类对象
- 类比: 陆上交通方式可以选择自行车、公交车或出租车
职责链模式(Chain of Responsibility)
- 描述:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止
- 关键实现:客户端抽象处理类类型的具体处理类对象A调用设置抽象处理类类型的具体处理类对象B为字段方法(指定下个处理者),A调用具体处理类的具体处理方法:处理请求(当前处理者有权处理),或B调用具体处理类的具体处理方法(当前处理者无权处理,交付给下个处理者处理)
- 类比: 联系客户服务询问电脑问题,若自动服务的方法无效就转接人工服务
状态模式(State):
- 描述:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类
- 关键实现:客户端上下文类对象A调用设置方法:参数接收抽象状态类类型的具体状态类对象B(当前状态,设置当前状态),A调用请求方法->B调用处理方法:参数发送A(this)->调用其他抽象状态类类型的具体状态类的构造方法创建抽象状态类类型的具体状态类对象C设置A(新状态,设置新状态)
- 理解:有上下文类对象A,抽象状态类类型的具体状态类对象B(当前状态)和其他抽象状态类类型的具体状态类对象C(新状态)。A设置当前状态为B:A持有B,A修改状态->B处理状态:B持有A->B设置A的新状态为C:A持有C(A字段B的改变委托给B修改成C)
- 其他:相对复杂的状态转换条件表达式->相对简单的不同状态类;运行时动态修改状态行为
- 类比: 手机在锁定状态时, 按键解锁,手机在解锁状态时, 按键执行功能
命令模式(Command):
- 描述:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作
- 关键实现:客户端抽象命令类类型的具体命令类对象B调用具体命令类的设置接收者类对象C为字段方法,发送者类对象A调用发送者类的设置抽象命令类类型的具体命令类对象B为字段方法,A调用发送者类的方法->B调用具体命令类的方法->C调用接收者类的方法(发送者类委托命令类,命令类委托接收者类;反向创建,正向通知)
- 相关内容:有记录、查找、撤销和重做操作的命令表/日志
- 类比: 顾客点餐到订单,服务员记录订单并通知厨师,厨师依据订单做餐
观察者模式(Observer):
- 描述:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
- 关键实现:客户端具体目标类对象A调用状态设置方法(状态改变),A调用通知方法(发送通知)->遍历抽象观察者类类型的具体观察者类对象B集合字段->B调用具体观察者类的更新方法(接收通知并自动更新)(目标通知观察者更新过程)
- 类比: 客户订阅报纸,出版社发布新一期报纸时通知客户
备忘录模式(Memento):
- 描述:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态
- 关键实现:客户端发起者类对象A调用创建备忘录方法->创建备忘录类对象B记录状态->B保存在管理者类对象C(保存记录),A调用恢复备忘录方法->从C获取B恢复状态(恢复记录)
- 类型:基于嵌套类的实现,基于接口的实现
- 相关内容:事务回滚/命令模式(Command)的撤销操作->备忘录模式(Memento)
- 类比: 游戏进度的保存和恢复
迭代器模式(Iterator):
- 描述:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示
- 关键实现:客户端当前具体集合类对象A调用具体集合类的具体创建迭代器方法创建抽象迭代器类类型的具体迭代器类对象B:参数发送A(this)(一个集合有多个迭代器,每个迭代器都持有集合),B调用具体迭代器类的具体获取起始对象方法和具体获取下个对象方法->A调用具体集合类的具体获取起始对象方法和具体获取下个对象方法(迭代器从集合中获取起始迭代器和下个迭代器)
- 其他:部分编程语言已封装实现迭代/遍历接口
- 类比: 旅游向导带领旅客依次参观各个景点
解释器模式(Interpreter):
- 描述:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
- 关键实现:客户端抽象表达式类类型的非终结符表达式类对象(树枝)调用非终结符表达式类的具体解释方法->抽象表达式类类型的终结符表达式类对象(树叶)调用具体解释方法:参数接收上下文类对象,执行相关操作(反向创建:先创建树枝,后创建树叶;正向解释:先解释树枝,后解释树叶;可能是树状递归的解释方式)
- 类比: 客户语音命令音箱播放音乐,音箱解释器将语音解释成信息,将信息解释成指令并完成任务
中介者模式(Mediator):
- 描述:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
- 关键实现:客户端当前具体组件类对象A和其他具体组件类对象C调用抽象组件类的设置抽象中介者类类型的具体中介者类对象为字段方法(组件A和组件C认识中介者B),具体中介者类对象B调用具体中介者类的设置具体组件类对象为字段方法(B认识A和C),A调用具体组件类的具体发送方法:参数接收信息(A发送信息)->B调用具体中介者类的具体通知方法:参数接收A(this)和信息(A委托B发送通知)->C调用具体组件类的具体接收方法:参数接收信息(C接收B的通知)
- 理解:有组件A,中介者B,组件C。A和C认识B,B认识A和C,A发送信息->A委托B发送通知->C接收B的通知
- 类比: 当前用户通过手机和网络发送信息,其他用户通过手机和网络接收信息
访问者模式(Visitor):
- 描述:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作
- 关键实现:客户端对象结构类对象A调用对象结构类的接收方法:参数接收抽象访问者类类型的具体访问者类对象B,遍历抽象元素类类型的具体元素类对象C集合->C调用具体元素类的接收方法:参数接收B->B调用具体访问者类的访问方法,参数接收C(this),使用C执行相关操作
- 理解:B的访问过程:客户端->A(第一次分派)->C->B(第二次分派),B使用C
- 相关内容:双分派
- 类比: 保险推销员依据建筑物类型提供不同保单:为居民楼推销医疗保险,为银行推销失窃保险
- 类比理解:稳定的数据结构:医疗保险和失窃保险,变化的算法/行为/访问者:居民楼和银行。访问者访问:保险推销员依据建筑物类型(第一次分派),提供不同保单(保单中信息和建筑物类型相关)(第二次分派)
设计模式的记忆方式/总结
面向对象特性的体现:
- 所有设计模式都基于面向对象,都体现封装特性
- 单例模式(Singleton),外观模式(Facade),备忘录模式(Memento)未体现继承和多态特性
创建型设计模式的简单复杂性:
- 相对简单:单例模式(Singleton),简单工厂模式(Simple Factory),原型模式(Prototype)
- 相对不简单不复杂:工厂方法模式(Factory Method)
- 相对复杂:抽象工厂模式(Abstract Factory),建造者模式(Builder)
结构型设计模式的简单复杂性:
- 相对简单:代理模式(Proxy),适配器模式(Adapter),外观模式(Facade)
- 相对不简单不复杂:组合模式(Composite),桥接模式(Bridge)
- 相对复杂:装饰模式(Decorator),享元模式(Flyweight)
行为型设计模式的简单复杂性:
- 相对简单:模板方法模式(Template Method),策略模式(Strategy),备忘录模式(Memento)
- 相对不简单不复杂:职责链模式(Chain of Responsibility),命令模式(Command),观察者模式(Observer),迭代器模式(Iterator),解释器模式(Interpreter)
- 相对复杂:状态模式(State),中介者模式(Mediator),访问者模式(Visitor)
创建型设计模式的关系:
- 三工厂:简单工厂模式(Simple Factory),工厂方法模式(Factory Method),抽象工厂模式(Abstract Factory)
结构型设计模式的关系:
- 结构型设计模式中除享元模式(Flyweight),其他6种设计模式:代理模式(Proxy),适配器模式(Adapter),外观模式(Facade),装饰模式(Decorator),桥接模式(Bridge)的关键实现相似:使用关联、聚合/组合关系,职责委托
- 外观模式(Facade)侧重搭配不同行为方案;建造者模式(Builder)侧重相同过程建造不同产品
- 装饰模式(Decorator)侧重装饰过程不稳定/灵活;建造者模式(Builder)侧重建造过程稳定
- 享元模式(Flyweight)和单例模式(Singleton)的关键实现类似
- 享元模式(Flyweight)侧重实例多个,不可变化;单例模式(Singleton)侧重实例一个,可变化
行为型设计模式的关系:
- 策略模式(Strategy)侧重多样表现的行为;简单工厂模式(Simple Factory)侧重多样实例的创建
- 策略模式(Strategy)使用关联、聚合/组合关系,职责委托
- 策略模式(Strategy)侧重算法系列相同,类型不同;模板方法模式(Template Method)侧重算法过程相同,具体步骤实现不同
- 职责链模式(Chain of Responsibility)侧重委托传递;代理模式(Proxy)侧重职责委托
- 命令模式(Command)侧重发送者、命令和接收者三者间的委托传递,三者身份/职责不同;职责链模式(Chain of Responsibility)侧重多者间的委托传递,多者地位/权限不同,职责相似
- 观察者模式(Observer)侧重一个通知者发送通知,多个观察者接收通知并自动更新,通知者和观察者的行为关系浅、不相关:只是通知关系;命令模式(Command)侧重发送者、命令和接收者间的职责/命令委托传递,三者的行为关系深、相关:为共同完成行为的命令关系
- 备忘录模式(Memento)侧重状态的记录和恢复;命令模式(Command)侧重命令的记录和传递
- 迭代器模式(Iterator)侧重分离集合对象的遍历行为;职责链模式(Chain of Responsibility)侧重委托的传递和处理
- 解释器模式(Interpreter)侧重分离解释行为,可能是树状递归的解释方式;组合模式(Composite)侧重处理组织结构,大多数是树状递归的组织结构
- 中介者模式(Mediator)侧重当前组件的消息通过中介者通知其他组件;观察者模式(Observer)侧重通知者的状态发生变化就通知观察者
- 访问者模式(Visitor)侧重分离稳定的数据结构和变化的算法/行为/访问者。算法访问数据结构(第一次分派),依据数据结构执行相关操作(第二次分派);状态模式(State)侧重状态变化,状态互相知道其他存在;策略模式(Strategy)侧重策略选择,策略互相不知道其他存在
架构模式简述
- 模型视图控制器模式(MVC)是多种设计模式(组合模式(Composite),策略模式(Strategy)和观察者模式(Observer))的综合应用,归为架构模式
- 典型三层架构:表示层,业务逻辑层,数据访问层
- 客户机/服务器(C/S)架构,浏览器/服务器(B/S)架构,客户机/服务器(C/S)和浏览器/服务器(B/S)混合架构
总结
设计模式总结。
参考资料
- 《大话设计模式》作者:程杰
- 常用设计模式有哪些? (refactoringguru.cn)
- 设计模式概述_夜悊的博客-CSDN博客
- 创建型设计模式总结_夜悊的博客-CSDN博客
- 结构型设计模式总结_夜悊的博客-CSDN博客
- 行为型设计模式总结_夜悊的博客-CSDN博客
- 依赖、关联、聚合和组合之间区别_木易不是楊的博客-CSDN博客_关联和聚合的区别
- 设计模式六大原则是什么-常见问题-PHP中文网
- GoF设计模式(十五):Interpreter Pattern 解释器模式 - 知乎 (zhihu.com)
作者的话
- 感谢参考资料的作者/博主
- 作者:夜悊
- 版权所有,转载请注明出处,谢谢~
- 如果文章对你有帮助,请点个赞或加个粉丝吧,你的支持就是作者的动力~
- 文章在描述时有疑惑的地方,请留言,定会一一耐心讨论、解答
- 文章在认识上有错误的地方, 敬请批评指正
- 望读者们都能有所收获