设计模式总结

前言

最近复习了一下设计模式的东西,从设计模式原则到具体模式的动机,定义,结构图做了一些整理,模式详细介绍部分参考李建中老师讲解时的ppt

设计原则

  1. 依赖倒置原则(DIP)
    高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定)
    抽象(稳定)不应该依赖于实现细节(变化),实现细节应该依赖于抽象(稳定)
  2. 开闭原则(OCP)
    对拓展开放,对修改关闭
    类模块应该是可拓展的但不可修改
  3. 单一职责原则(SRP)
    一个类应该只有一个引起它变化的原因
    变化的方向隐含着类的责任
  4. 里氏替换原则(LSP)
    子类必须能替换他们的基类(is-a)
    继承表达类型抽象
  5. 接口隔离原则(ISP)
    接口小而完备
    不能让客户依赖他们不用的东西
  6. 优先使用组合而不是继承
    类继承为白箱复用,而组合是黑箱复用
    继承在一定程度上破坏了封装性,子类父类耦合高
    组合只要求被组合的对象有良好的接口,耦合度低
  7. 封装变化点
    使用封装来创建分解层,让使用者可以在一侧修改不影响另一侧,实现层次间的松耦合
  8. 针对接口编程,而不是针对实现编程
    不将变量声明为某个具体类,而是声明为一个接口
    客户无需获取具体类型只需要知道接口
    减少各部分依赖实现“高内聚,松耦合”

设计模式

设计模式划分

从目的来看:
• 创建型(Creational)模式:将对象的部分创建工作延迟到子 类或者其他对象,从而应对需求变化为对象创建时具体类型实 现引来的冲击。
• 结构型(Structural)模式:通过类继承或者对象组合获得更灵 活的结构,从而应对需求变化为对象的结构带来的冲击。
• 行为型(Behavioral)模式:通过类继承或者对象组合来划分 类与对象间的职责,从而应对需求变化为多个交互的对象带来 的冲击。
在这里插入图片描述

下面对各种设计模式进行分别介绍

创建型设计模式

单例模式

动机:
在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能保证它们的逻辑正确性和良好的效率
定义:
保证一个类仅有一个实例,并提供一个该实例的全局访问点。下面是简单的类图,单例有懒汉模式饿汉模式,可自己选择,多线程问题,C++11后可采用局部静态变量的方式简单处理。
结构图:
在这里插入图片描述

工厂模式

动机
在软件系统中,经常面对着创建对象的工作,由于需求变化,需要创建的对象的具体类型经常变化。如何应对这种变化,绕开常规的对象创建方法,提供一种“封装机制”来避免客户端和这种“具体对象创建工作”的紧耦合。
定义:
定义一个用于创建对象的接口,让子类决定实例化那个类。工厂模式让一个类的实例化延迟到子类。
结构图:
在这里插入图片描述

抽象工厂

动机
在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求变化,往往存在着更多系列对象的创建工作。如何应对这些变化?如何绕过常规的对象创建方法,提供一种“封装机制”来避免客户端程序和这种“多系列具体对象创建工作的紧耦合”。
模式定义:
提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。
结构图:
在这里插入图片描述

工厂模式和抽象工厂模式稍作对比

在这里插入图片描述

原型模式

动机:
在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但它们却有比较稳定的接口。如何应对这种变化?如何向“客户程序”隔离出“这些易变的对象”,从而使得“依赖这些易变对象的客户程序”不随需求改变而改变?
定义:
使用原型实例指定创建对象的种类,然后通过拷贝创建新的对象
结构图:
主要就是clone方法
在这里插入图片描述

建造者模式

动机
在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将他们组合在一起的算法相对稳定。如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随需求改变而改变?
定义:
将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)
结构图:
在这里插入图片描述

结构型

适配器模式

动机
在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放到新的应用环境中,但是新环境要求的接口是这些现存对象不满足的。如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所需接口?
定义:
将一个类的接口转换为客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的类可以一起工作
结构图:
在这里插入图片描述

桥接模式

动机:
由于某些类型的固有的实现逻辑,使得它们具有两个维度的变化,乃至于多个维度的变化。如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松的沿着两个乃至多个方向变化,而不引入新的额外复杂度。
定义:
将抽象部分(业务功能)与实现部分(平台实现)分离,使得它们都能独立的变化
结构图:
在这里插入图片描述

组合模式

动机:
在某些情况下,客户代码过多的依赖对象容器内部复杂的实现结构,对象容器内部实现结构(而非抽象接口)的变化将引起客户代码频繁变化,带来代码的维护性,拓展性的弊端。如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客户端代码像处理简单对象一样处理复杂的对象容器?
定义:
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
结构:
应该是1:n的关系
在这里插入图片描述

装饰模式

在某些情况下我们可能会“过度的使用继承来扩展对象的功能”,由于继承为类引入的静态特质,使得这种拓展方式缺乏灵活性;随着子类的增多(拓展功能的增多),各种子类的组合(拓展功能的组合)会导致更多子类的膨胀。如何使“对象功能的拓展”能够根据需要来动态的实现?如何避免“拓展功能的增多”带来的子类膨胀问题?从而使得任何“功能拓展变化”所导致的影响降为最低?
模式定义:
动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,装饰模式比生成子类(继承)更为灵活(消除重复代码 & 减少子类个数)。
结构图:
在这里插入图片描述

外观模式

动机:
组件的客户和组件中各种复杂的子系统有了过多的耦合,随着外部客户程序和子系统的演化。这种过多的耦合面临着很多变化的挑战。
如何简化外部客户程序和系统间交换的接口?如何将外部客户程序的演化和内部子系统的变化之间的依赖相互解耦
定义:
为子系统的一组接口提供一个一致(稳定)的界面,Façade模式定义了一个高层接口,这个接口使得这一子系统更加容易复用
结构图:
在这里插入图片描述

享元模式

动机
在系统中采用纯粹的对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而产生很高的运行时代价—主要指内存需求的代价
如何避免大量细粒度对象问题的同时让外部客户程序仍然能透明的使用面向对象的方式来操作?
定义:
通过运用共享技术有效的支持大量细粒度对象。
结构图:
在这里插入图片描述

代理模式

动机
在面向对象的系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外访问等),直接访问会给使用者、系统结构带来很多麻烦。如何在不失去透明操作对象的同时来管理/控制这些对象的复杂性?增加一层间接层是软件开发中常见的解决方法
模式定义:
为其他对象提供一种代理以控制(隔离,使用接口)对这个对象的访问
结构图:
在这里插入图片描述

行为型

解释器模式

在软件构建过程中,如果某一特定的领域问题比较复杂,类似的结构不断出现,如果使用普遍的编程方式来实现将面临非常频繁的变化。在这种情况下,将特定的领域问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的
模式定义:
给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器用来解释语言中的句子。
结构图:
在这里插入图片描述

模板模式

动机:
在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架和应用之间的关系)而无法和任务的整体结构同时实现。如何在确定稳定操作结构的前提下,来灵活的应对各个子步骤的变化或晚期的实现需求
模式定义:
定义一个操作中算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。模板模式使得子类可以不改变一个算法道得结构即可重定义该算法的特定步骤
结构图:
在这里插入图片描述

职责链模式

动机:
在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显式指定,将必不可少的带来发送者和接收者的紧耦合。如何使请求的发送者不需要指定具体的接收者?让请求的接收者自己在运行时决定来处理请求,从而使两者解耦
定义:
使得多个对象都有机会来处理请求,从而避免请求的发送者和接收之间的耦合关系,将这些对象连成一条链,并将请求沿着这条链传递,直到有一个对象处理它为止
结构图:
在这里插入图片描述

命令模式

动机:
在软件构建过程中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合—比如需要对行为进行“记录、撤销/重(undo/redo)、事务“等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将”行为请求者“和”行为实现者“解耦?将一组行为抽象为对象,可以实现二者间的松耦合
定义:
将一个请求(行为)封装为一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作
结构图:
在这里插入图片描述

迭代器模式

动机
在软件构建过程中,集合对象内部结构常常变化各异,但对于这些集合对象,我们希望不爆露其内部结构的同时,可以让外部客户代码透明的访问其中包含的元素;同时这种“透明遍历“也为”同一种算法在多种集合对象上进行操作“提供了可能
使用面向对象技术将这种遍历机制抽象为“迭代器对象“为”应对变化中的集合对象“提供了一种优雅的方式
定义
提供一种方法顺序访问聚合对象中的各个元素,而又不暴露(稳定)该对象的内部表示
结构图:
在这里插入图片描述
STL中迭代器很完善了,这个使用不多了

中介者模式

动机
在软件构建过程中,经常出现多个对象相互关联的情况,对象之间常常会维持一种复杂的引用关系,如果遇到一些需求的变更,这种直接引用的关系会面临不断变化。这种情况下,我们可以使用一个“中介对象“来管理对象之间的关联关系,避免相互交互的对象之间的紧耦合的引用关系,从而更好的抵御变化
模式定义:
用一个中介对象来封装(封装变化)一系列的对象交互,中介者使各对象之间不需要显shi的相互引用(编译时依赖-)运行时依赖),从而使其耦合松散(管理变化),且可以独立的改变它们之间的交互。
结构图:
在这里插入图片描述

备忘录模式

动机:
在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前在某个点所处的状态。如果使用一些公有接口来让其他对象得到对象状态,便会暴露对象的细节实现。如何实现对象状态的良好保存和恢复?但同时又不会因此破坏对象本身的封装性
定义:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就能将该对象恢复到先前保存的状态
结构图:
在这里插入图片描述

观察者模式

动机:
在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”—一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使得软件不能很好的抵御变化。使用面向对象的技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系的松耦合。
定义:
定义对象间的一种一对多的(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
结构图:
在这里插入图片描述

状态模式

动机:
在软件构建的过程中,某些对象的状态如果发生改变,其行为也会随之改变,比如文档处于只读状态,其支持的行为和读写状态就可能完全不同。如何在运行时根据对象状态来透明的更改对象的行为?而不会为对象操作和状态转换之间引入紧耦合?
定义:
允许对象在其内部状态改变时改变它的行为,从而使对象看起来似乎修改了其行为。
结构图:
在这里插入图片描述

策略模式

动机:
在软件构建的过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使得对象变得异常复杂,而且有时候支持不使用的算法也是一个性能负担。如何在运行时根据需要透明的更改对象的算法?将算法与对象本身解耦,从而避免上述问题?
定义:
定义一系列的算法,把他们一个个的封装起来,并且使他们可以互相替换(变化)。该模式使得算法可以独立于使用它的客户程序(稳定)而变化(拓展,子类化)
结构图:
在这里插入图片描述

访问者模式

动机:
在软件构建过程中,由于需求的改变,某些类层次结构常常需要增加新的行为(方法),如果直接在基类中做这样的更改,将会给子类带来繁重的变更负担,甚至破坏原有设计。如何在不变更类层次结构的前提下,在运行时根据需要透明的为类层次结构上的各个类动态添加新的操作,从而避免上述问题?
定义:
表示一个作用于某对象结构中各个元素的操作。使得可以在不改变(稳定)各元素的类的前提下定义(拓展)作用于这些元素的新操作(变化)
结构图:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值