设计模式概述

预览

名称 定义
策略模式 封装了算法,为不同的算法提供统一的接口
单一职责 就一个类而言,应当仅有一个引起它变化的原因
开放封闭原则 类、模块、函数可以扩展,但是不可以修改
依赖倒转原则 抽象不应该依赖细节,细节应该依赖于抽象
里氏替换原则 子类型必须能够替换掉它们的父类型
装饰模式 动态的给对象添加额外的职责
代理模式 为其他对象提供一种代理以控制对这个对象的访问
工厂模式 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类
模版方法 定义封装算法的骨架,而将特定的细节交由子类实现
建造者模式 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的应用

策略模式

定义

它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变换不会影响到使用算法的客户

优点

  • 策略模式定义了一系列算法,这些算法完成相同的工作,只是实现不同,策略模式可以以相同的方式调用所有算法,减少了算法和使用算法类之间的耦合。
  • 易于进行单元测试

使用场景

测旅模式可以封装任何类型的规则,只要在分析过程中需要在不同时间应用的业务规则,就可以使用策略模式处理这种变化的可能性。

单一职责

定义

就一个类而言,应当仅有一个引起它变化的原因

为何需要单一职责

当一个类承担的职责太多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或抑制这个类完成其他职责的能力,这种耦合会导致脆弱的设计,当变化发生时,设计会遭到意想不到的破坏

何时需要职责分离

如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责

开放封闭原则

  • 无论模块是多么的”封闭”,都会存在一些无法对之封闭的变化,既然不可能完全封闭,设计人员必须对他设计的模块应该对那种变化封闭做出选择,他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那么变化。
  • 等到变化发生时立即采取行动
  • 面对需求,对程序的改动是通过增加薪代码进行的,而不是更改现有的代码
  • 开发人员应改仅对程序中频繁变化的那些部分做出抽象

依赖倒转原则

  • 高层模块不应该依赖低层模块,两个都应该依赖抽象
  • 抽象不应该依赖细节。细节应该依赖抽象
  • 依赖倒转可以说是面向对象设计的标志,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计。

里氏替换原则

  • 只有当子类可以替换掉父类,软件单位的功能不受影响时,父类才能真正被复用,而子类也能够在父类基础上增加新的行为。
  • 由于子类的可替换性才使得使用父类类型的模块在无需修改的情况下可以扩展。

装饰模式 (Decorator)

动态地给对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

  • 装饰模式是为已有功能动态的添加更多功能的一种方式
  • 当系统需要新的功能时,把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象。
  • 装饰模式有效的将核心职责和装饰功能区分开,而且可以去除相关类中重复的装饰逻辑。

代理模式

为其他对象提供一种代理以控制对这个对象的访问。

  • 远程代理,为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
  • 虚拟代理,是根据需要创建开销很大的对象,通过它存放实例化需要很长时间的真实对象。
  • 安全代理,用来控制真实对象访问时的权限。
  • 智能指引,是指当调用真实对象时,代理处理另外一些事。

工厂方法模式

  • 简单工厂模式的最大优点在于工厂类中包含必要的逻辑判断,根据客户端的选择条件动态实例化相关类,对客户端来说,去除了于具体产品的依赖。
  • 工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在,也就是说工厂方法把简单工厂的内部逻辑判断移到来客户端代码来进行。

模版方法

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

  • 模版方法模式是通过把不变行为搬移到超类,去除子类中重复的代码来体现它的优势
  • 当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模版方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。

迪米特法则

如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

  • 迪米特法则的前提是,每个类都应当尽量降低成员的访问权限
  • 迪米特法则的根本思想是强调类与类之间的松耦合。
  • 类之间的耦合越弱,越有利于复用。

外观 (Facade) 模式

为子系统中的一组接口提供一个一致的界面,此模式定义来一个高层接口,这个接口使得这一子系统更加容易使用

用途

  • 在设计初期应该有意识的将不同的两个层分离,例如典型的 MVN 结构
  • 在开发阶段,随着系统不断重构演化而变得越来越复杂,增加外观可以提供一个简单的接口,减少它们之间的依赖
  • 维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展,为新系统开发一个外观 Facade 类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与 Facade 对象交互。

建造者模式 (Builder)

用途

主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。
建造者模式是在当创建复杂对象的算法应该独立与该对象的组成部分以及它们的装配方式时适用的模式

优势

使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。

观察者模式 (Observer)

又称发布订阅模式 (Publish/Subscribe)
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

优势

  • 观察者模式所做的工作其实就是在解除耦合。让偶和的双方都依赖于抽象,而不是具体的实现。
  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立的改变和复用。

用途

  • 将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使得各类紧密耦合。
  • 当一个对象的改变需要同时改变其他对象时,而且它不知道有多少个对象有待改变。