Table of Contents
本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对c/c++linux系统提升感兴趣的读者,可以点击链接,详细查看详细的服务:
服务器课程:https://course.0voice.com/v1/course/intro?courseId=5&agentId=0
音视频:https://course.0voice.com/v1/course/intro?courseId=3&agentId=0
dpdk:https://course.0voice.com/v1/course/intro?courseId=4&agentId=0
内核:https://course.0voice.com/v1/course/intro?courseId=2&agentId=0
定义
设计模式是指在软件开发中,经过验证的,用于解决在特定环境下,重复出现的,特定问题的解决方案。
设计原则
依赖倒置
- 高层模块不应该依赖底层模块, 两者都应该依赖抽象
- 抽象不应该依赖具体实现, 具体实现应该依赖于抽象
开放封闭
- 一个类应该对扩展(组合和继承)开放,对修改关闭
面向接口
- 不将变量类型声明为某个特定的具体类型,而是声明为某个接口
- 客户程序无需获知对象的具体类型,只需要知道对象所具有的接口
- 减少系统中各部分的依赖关系,从而实现“高内聚,低耦合”的类型涉及方案
封装变化点
- 将稳定点和变化点分离,扩展修改变化点
- 让稳定点和变化点的实现层次分离
单一职责
- 一个类应该仅有一个引起它变化的原因
里氏替换
- 子类型必须能够替换掉它的父类型;主要出现在子类覆盖父类实现,原来使用父类型的程序可能出错;
覆盖了父类方法却没有实现父类方法的职责,也就是说子类尽量不要重写父类的方法
接口隔离
- 不应该强迫客户依赖于他们不用的方法
- 一般用于处理一个类拥有比较多的接口,而这些接口涉及到很多职责
- 客户端不应该依赖他不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上
组合由于继承
- 继承耦合度高,组合耦合度低
目录
模板方法 Template Method
一种行为设计模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法
的结构即可重定义该算法的某些特定步骤 – GoF
将算法分解为一系列步骤,让后将这些步骤改写为方法,最后在“模板方法”中一次调用这些方法。
步骤可以是抽象的,也可以有默认实现。
- 例如在标准的房屋建造方案中可提供几个扩展点,允许业主调整成品房屋的部分细节;其中每个步骤例如
建造墙壁、地砖都能进行微调
- 例如为策略游戏中的 NPC 设定不同的细节能力,如半兽人更富攻击性,让人类侧重防守
观察者模式 Observer
一种行为设计模式
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象的状态发生改变时,所有依赖与他的对象都
得到通知并自动更新 – GoF
拥有值得关注的状态的对象被成为目标 subject,由于它要将自身状态的改变通知给其他对象——也被称为
发布者 publisher;关注发布者状态变化的其他对象被称为订阅者 subscribers。
注意点:
- 订阅者必须实现同样的接口
- 观察者自己决定是否订阅通知,目标对象并不关注谁订阅了
- 订阅者的通知顺序是随机的
策略模式 Strategy
定义一系列算法,把他们一个个封装起来,并且使他们可互相替换。该模式使得算法可独立于使用它的
客户程序而变化 – GoFhttps://refactoringguru.cn/design-patterns/strategy
一种行为涉及模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够
相互替换建议找出负责用许多不同方式完成特定任务的类,然后将其中的算法抽取到一组被称为策略的独立类中
名为上下文的原始类不负责选择符合任务需要的算法,而客户端会将所需策略传递给上下文,上下文会
通过同样的接口与所有策略进行交互
单例模式 Singleton
保证一个类仅有一个实例,并提供一个该实例的全局访问点 – GoF
工厂方法 Factory Method
定义一个用于创建对象的接口,让子类决定实例化哪一个类。
使得一个类的实例化延迟到子类 – GoF
接口作用:抽象稳定点
其中注意接口区分为 职责接口 与 工厂接口(对象产生)
为什么要有工厂,而不直接使用 new?
- new 之后还有复杂的构造流程;需解决创建过程复杂,并且对外隐藏这些细节
- eg:连接池、线程池
- 设计原则:
- 最小知道原则
- 面向接口编程
- 稳定点
- 创建同类对象的接口;对象创建接口
- 同类对象有一个相同的职责;功能接口
工厂方法将产品创建代码与实际使用代码相分离,如需添加一种新的产品,只需开发新的创建者子类,然后
重写其工厂方法即可
抽象工厂 Abstract Factory
提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类 – GoF
假设你在开一家家具城,你需要确保给一个顾客生成的都是风格一致的家具;(客户只关注到手的风格相同)
解决方案:
- 为系列中的每件产品都明确声明接口,例如椅子、沙发
- 确保所有产品变体都继承这些接口,例如所有风格的椅子都实现椅子接口
- 声明抽象工厂,包含系列中所有产品构造方法的接口,例如 CreateChari、CreateSofa
- 对于系列变体,都将基于抽象工厂接口创建不同的工厂类,每个工厂类都只能返回特定类别的产品
- 客户端最终只需知道,无论是椅子还是沙发,它们都由同一风格的工厂对象创建
- 一般程序会根据配置文件或环境设定来选择工厂类别,并在初始化阶段创建工厂对象
适用场景:抽象工厂为你提供了一个可用于创建每个系列产品对象的接口,并保证只要代码通过该接口创建
对象,那么你就一定得到的是与应用程序已产生的产品类型一致的产品
工长方法与抽象工厂区别:
- 抽象工厂有多个职责
- 抽象工厂模式通常基于一组工厂方法
责任链 Chain of Responsibility
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这
条链传递请求,直到有一个对象处理它为止。 – GoF
每个处理者均可对请求进行处理,或将其传递给链上的下一处理者
链上的每个处理者都有一个成员变量来保存下一个处理者的引用
处理者可决定不再沿着链传递请求
- 稳定点
- 处理流程
- 请求沿着链条传递
- 可打断
- 处理流程
- 变化点
- 处理节点的个数
- 处理顺序
- 处理条件
- 设计原则
- 组合优于继承
- 面向接口编程
- 接口依赖
装饰器 Decorator
动态地给一个对象增加一些额外的职责;就增加功能而言,装饰器模式比生产子类更为灵活
封装器是能与其他目标对象连接的对象,封装器包含与目标对象相同的一系列方法
封装器在将收到的请求委派给目标对象前或后,进行处理,以可能改变最终结果
封装器实现了与其封装对象相同的接口,因此从客户端的角度来看这些对象时完全一致的
封装器中的引用成员变量可以使 遵循相同接口的 任意对象,这使得你可以在对象中添加所有这些封装器的组合行为
- 稳定点
- 增加职责
- 顺序无关地增加职责
- 变化点
- 职责会不断膨胀