设计模式读书笔记

2023-11-17

希望通过记录一些关键点做到实际开发中能够得心应手。

目录

状态模式

策略模式

观察者模式

装饰者模式

适配器模式 

外观模式

抽象工厂模式

工厂方法模式 

单例模式

命令模式

模板方法模式 

迭代器模式 

组合模式 

代理模式

建造者模式 

桥接(Bridge)模式

责任链模式

中介者模式

原型模式(Prototype)

模型-视图-控制器


状态模式

这个模式可能工作中会遇到,将可以互换的行为封装起来,然后使用委托的方法,决定使用哪一个行为,状态基转移场景

这种设计会大量新增状态类,对于一些复杂场景会非常管用;对一些简单场景,比如状态里面只有一个处理函数,状态基转换也比较简单,顺序递增,可能只需要封装函数即可。

int state = 0;
switch (state) {
    case 0:
        DoStateStart();
        break;
    case 1:
        DoStateProcess();
        break;
    case 2:
        DoStateStop();
        break;
    default:
        break;
}

void DoStateStart()
{
    ...
    state++;
}

void DoStateProcess()
{
    ...
    state++;
}

void DoStateStop()
{
    ...
    state = 0;
}

策略模式

定义算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。这也是“多用组合,少用继承”的设计原则,用HAS-A(有一个)代替IS-A(是一个)

继承:

组合: 

 

观察者模式

定义了对象只看的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新

        观察者是否需要持有被观察者对象的实例?持有的话,由观察者调用被观察者的注册接口和取消注册接口,但是被观察者的生命周期需要关注和管理

        观察者通过notifyObserver接口通知被观察者,这是push,而不是被观察者来调用观察者的接口,这是pull。

        这里的被观察者可以搞个继承,需要被观察的的都继承自Observalbe,它里面包含必须要实现的两个函数:registerObserver()和notifyObserver()

装饰者模式

目的是想在原来的基类的基础上增加些功能,一种设计思想是通过继承的方式不断增加子类,而且需要不可避免的修改基类的函数,可能代码长这样

class Base
{
    virtual int Cost()
    {
        int cost = 0;
        if (HasTea()) {
            cost += 2;
        }

        if (HasMilk()) {
            cost += 3;
        }
    }

    virtual bool HasTea() = 0;
    virtual bool HasMilk() = 0;
}

class A : public Base
{
    virtual bool HasTea() {return false;}
}

class B : public Base
{
    virtual bool HasMilk() {return true;}
}

这种设计违反了设计原则:开放-关闭原则,类应该对扩展开放,对修改关闭 。也就是基类在稳定之后尽可能不要再修改

装饰者和被装饰者应该具有相同的基类,或者装饰者要继承被装饰者,这样做的目的是为了在使用被装饰者的地方可以使用装饰者替代;这里使用继承的目的仅此而已;装饰者内部需要引用被装饰者,装饰者可以在所委托被装饰者的行为之前或之后,加上自己的行为,以打到特定的目的。装饰者定义;我们平时使用I/O相关类使用的就是装饰者设计模式,另外可以有多层包装,

Component* component = new Decorator2(Decorator1(ConcreteComponent()));

适配器模式 

将一个类的接口,转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以合作

外观模式

提供了一个统一的接口,用来访问子系统中的 一群接口,外观定义了一个高层接口,让子系统更容易使用

 

抽象工厂模式

 允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么,这样一来,客户就从具体的产品中被解耦。

该模式解决了一种依赖:客户代码不再依赖具体的产品子类,只依赖工厂类返回的抽象类。这叫做依赖倒置原则,客户代码依赖抽象类,产品子类也依赖这个抽象类。这也是我们说的的要依赖接口编程,而不是依赖实现编程

工厂方法模式 

抽象工厂模式和工厂方法模式的区别:

抽象工厂模式-与-工厂方法模式区别_wangwenhui11的博客-CSDN博客_工厂方法模式和抽象工厂模式的区别

它的里面是一堆工厂方法,每个工厂方法返回某种类型的对象。

比如说工厂可以生产鼠标和键盘。那么抽象工厂的实现类(它的某个具体子类)的对象都可以生产鼠标和键盘,但可能工厂A生产的是罗技的键盘和鼠标,工厂B是微软的。

这样A和B就是工厂,对应于抽象工厂;
每个工厂生产的鼠标和键盘就是产品,对应于工厂方法;

用了工厂方法模式,你替换生成键盘的工厂方法,就可以把键盘从罗技换到微软。但是用了抽象工厂模式,你只要换家工厂,就可以同时替换鼠标和键盘一套。如果你要的产品有几十个,当然用抽象工厂模式一次替换全部最方便(这个工厂会替你用相应的工厂方法)

所以说抽象工厂就像工厂,而工厂方法则像是工厂的一种产品生产线

单例模式

 确保一个类只有一个实例,并提供一个全局访问点。单例模式相较于全局或静态变量来说,有个好处是可以延迟实例化。单例模式的代码看着比较简单,但是有很多的注意事项,比如用构造函数需要private,全局访问点需要加锁互斥等

还有个问题,单例模式就真的能确保单例吗?如果不同的动态库通过静态链接的方式引用,那这几个动态库是指向同一个单例吗?答案不是,动态库 静态库 混合使用下的单例模式bug - 知乎

 解决方案也就是将单例静态库编译成动态库,其他动态库通过动态库链接到该单例实例

命令模式

将请求和接收者封装成一个对象,这个对象只暴露出execute()方法,当此方法被调用时,接受者会执行一系列动作。工作中经常用到一个场景是将命令对象丢进一个队列里,有一个单独的线程从该队列里取出命令对象执行。

模板方法模式 

在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤

 钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定。

迭代器模式 

提供一种方法能够顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

组合模式 

允许将对象组成树形结构来表现“整体/部分”层次结构,组合能让客户以一致的方式处理个别对象以及对象组合。

代理模式

远程代理好比远程对象的本地代表

 代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问,被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象

经常讲到的一个例子是显示图像,在创建开销大的对象的时候,如果没有创建好先返回一个提示,同事创建异步线程创建对象,当对象真正创建完成之后再重新显示。

建造者模式 

设计模式之建造者(Builder)模式 - 阿Jay - 博客园

造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。

桥接(Bridge)模式

将抽象与实现分离,使它们都可以独立变化

 桥接模式如果抽象不变化的话,只有一个抽象和多个实现的话,那它就是最简单的接口与实现分离;Adapter模式和Bridge模式具有一些共同的特征,他们都给另一对象提供了一定程度的间接性,因而有利于系统的灵活性。它们的不同之处在于用途。Adapter主要为了解决两个已有接口之间不匹配的问题。Bridge模式是软件设计之初就考虑的,

责任链模式

责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

注意:责任链模式也叫职责链模式。

在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和请求的处理者解耦了。

中介者模式

中介者(Mediator)模式的定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。

中介者模式是一种对象行为型模式,其主要优点如下。

  1. 类之间各司其职,符合迪米特法则。
  2. 降低了对象之间的耦合性,使得对象易于独立地被复用。
  3. 将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。


其主要缺点是:中介者模式将原本多个对象直接的相互依赖变成了中介者和多个同事类的依赖关系。当同事类越多时,中介者就会越臃肿,变得复杂且难以维护。 

中介者模式和观察者模式的区别:中介者需要封装复杂的语义,

原型模式(Prototype)

 提供clone函数复制自己

C++是静态语言,运行时刻只能得到很少或者得不到任何类型信息。

一开始我的疑问点是为什么不直接调用该类的复制构造函数,但想想你拿到的指向子类的父类指针或引用,不可能调用子类的复制构造函数。

原型模式和抽象工厂模式在某些方面是竞争的,但原型模式有个好处是不需要增加新类。

享元模式

解释器模式

备忘录模式

访问者模式 

模型-视图-控制器

Model-View-Control,里面涉及的模式包括:

观察者模式:模型是被观察者,视图和控制器是观察者

策略模式:视图可以有不同的控制器

Mixin模式

多重继承

什么是Mixin模式:带实现的协议 - 走看看

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式读书笔记 的相关文章

随机推荐

  • [非线性控制理论]6_滑模控制 (sliding mode control)

    非线性控制理论 1 Lyapunov直接方法 非线性控制理论 2 不变性原理 非线性控制理论 3 基础反馈稳定控制器设计 非线性控制理论 4 反馈线性化 反步法 非线性控制理论 5 自适应控制器 Adaptive controller 非线
  • CF 935E - Fafa and Ancient Mathematics

    CF 935E Fafa and Ancient Mathematics 题目描述 定义合法数学表达式 E E E 为一个数或两个合法数学表达式中间加上一个加或减运算符 并且在外面加上一对括号 给定一个合法数学表达式 将其中加减运算符用
  • QML Image内部缓存导致的问题

    QML Image BUG BUG描述 两个界面login qml 和 modify qml 页面 内部代码大致如下 Camera id camera imageProcessing whiteBalanceMode CameraImage
  • python实现vlookup_干货一:怎么在python里面实现vlookup

    vlookup应该是excel里用的比较多的功能 我刚接触excel的时候 反正觉得这个功能非常神奇 省了很多事 但是用久了以后就发现vlookup的限制太多了 第一大痛点 只能往右边 gt 找 如果要往左边找 最笨的办法就是把要找的col
  • rpm软件包解读

    一 linux应用程序与系统命令关系 二 典型应用程序的目录结构 三 常见的软件包封装类型 RPM包管理工具 RPM软件包管理器RED HAT PACKAGE MANAGER 由Red Hat公司提出 被众多linux发行版所采用 建立统一
  • 【机器学习】Q-Learning详细介绍

    Q learning Q learning 是一种机器学习方法 它使模型能够通过采取正确的操作来迭代学习和改进 Q learning属于强化学习的算法 通过强化学习 可以训练机器学习模型来模仿动物或儿童的学习方式 好的行为会得到奖励或加强
  • 如何从几何角度上理解方程组只有一个解_线性方程组的解集及其几何意义

    由于这三者之间的等价关系 我们解决现实问题时可以自由选取其中任意一个作为模型 我个人认为 线性方程组是最 质朴 的形式 向量方程则是与几何建立了关系 这将方便我们进行更直观的推理 矩阵方程则是向量方程的一种 封装 是向量方程的一种抽象 它将
  • Hotspot 垃圾回收之ConcurrentMarkSweepThread 源码解析

    目录 一 ConcurrentGCThread 二 SurrogateLockerThread 1 make 2 loop manipulatePLL 三 ConcurrentMarkSweepThread 1 定义 2 start和构造方
  • 微服务系列(六) 服务熔断与服务降级

    一 背景 分布式系统环境下 服务间类似依赖非常常见 一个业务调用通常依赖多个基础服务 如下图 对于同步调用 当库存服务不可用时 商品服务请求线程被阻塞 当有大批量请求调用库存服务时 最终可能导致整个商品服务资源耗尽 无法继续对外提供服务 并
  • element-ui表格列el-table-column如何根据数据不同显示不同的值,获取prop值

    方法一 格式化数据 在使用element ui的表格时 有时候后台给你的字段和你要显示在表格列里的内容不一致 例如后台给的字段是state 它的值为true或false 要求显示在表格里是 正确 或 错误 这时可以给el table col
  • FreeRTOS轻量级同步--任务通知

    1 简介 在FreeRTOS的配置参数中的configUSE TASK NOTIFICATIONS宏打开 一般RTOS会默认打开 如图1所示 图1 notify宏开关 RTOS在创建任务时 会创建一个32位的通知值ulNotifiedVal
  • C#中await Task.Run 返回值

    using System using System Text using System Collections Generic using System Threading using System Threading Tasks name
  • Cadence Allegro PCB设计88问解析(十一) 之 Allegro中文件自动保存时间设置

    一个学习信号完整性的layout工程师 大家在设计图纸或者编辑文档时 最常点击的应该就是保存图标了 谁也不想因为软件闪退 电脑断电等情况 我们的劳动成果就白白的消失了 在我们用Allegro进行PCB设计 就会有一个自动保存的功能 每隔一段
  • 一文看懂L1、L2正则化的区别

    正则化是一种为了减小测试误差的行为 有时候会增加训练误差 我们在构造机器学习模型时 最终目的是让模型在面对新数据的时候 可以有很好的表现 当你用比较复杂的模型比如神经网络 去拟合数据时 很容易出现过拟合现象 训练集表现很好 测试集表现较差
  • 牛顿迭代法求解二元非线性方程组,C++代码实现

    整体迭代公式就是 上式中 为的雅克比矩阵 为雅克比矩阵的逆矩阵 实例 求解的x和y的解 上面求根问题可转化为的问题 即可用牛顿迭代法求解此二元非线性方程 具体求解过程代码如下所示 线性方程组中方程个数 未知量个数 include
  • 推荐书目

    深入理解计算机系统 原书第2版 作 者 美 Randal E Bryant David R O Hallaron 著 出 版 社 机械工业出版社 图书定价 99 00 准备看看 C C 从入门到高手所有必备PDF书籍收藏 喜欢的朋友支持下吧
  • 经典的python基础练习

    假设市面上有4种面值 硬币 20元 10元 5元 1元 输入一个钱数 能够使用最少的硬币凑成这个钱数 def mon money ss 0 0 0 0 coinKinds 20 10 5 1 for i in range len coinK
  • 代码覆盖率与测试覆盖率你选哪个?

    目录 一 概念 二 代码覆盖率 三 为什么要执行代码覆盖率 四 如何执行代码覆盖率 五 代码覆盖率工具 六 测试覆盖率 七 如何执行测试覆盖率 八 测试覆盖率工具 九 代码覆盖率与测试覆盖率 哪一个 十 测试覆盖范围的优势 十一 测试覆盖范
  • 2017年全国数学建模国赛B题题目、解题思路、matlab代码(三)

    题目 移动互联网的迅速发展使得任务完成新模式 众包 的实现成为可能 这种自助式服务模式以移动互联网为劳务众包平台 通过线上 APP 建立起需要商业检查和信息搜集的企业与可以完成规定任务的大众之间的联系 从而大大节省企业调查成本 有效地保证调
  • 设计模式读书笔记

    希望通过记录一些关键点做到实际开发中能够得心应手 目录 状态模式 策略模式 观察者模式 装饰者模式 适配器模式 外观模式 抽象工厂模式 工厂方法模式 单例模式 命令模式 模板方法模式 迭代器模式 组合模式 代理模式 建造者模式 桥接 Bri