X

曜彤.手记

随记,关于互联网技术、产品与创业

设计模式速谈:一、序论

大家在平时的日常工作开发中,可能经常会听到“设计模式”这个词,那么到底什么是设计模式呢?如果要是按照课本上的方式来讲解,估计十篇博客也无法将它讲解透彻。“设计模式”的理论知识固然重要,但理论也是为了实践所做的基础,不要仅被理论就搞昏了头脑。

“设计模式”顾名思义,就是设计软件体系时所使用的一系列模式,而这些模式是不会变化的或者说只会在很小的程度上变化,但每种模式的整体结构是基本不变的。所以可以说,每一种设计模式都对应着一种问题的解决方法。而如果需要在项目中使用这些方法,就要看哪一种设计模式更加适合自己的项目结构了。抽象的讲,设计模式是可以解决一类软件问题并能够重复使用的软件设计方法。

“设计模式”是可复用的,也就是说很多结构或功能十分相似的工程项目均可以使用同一种“设计模式”来处理。在选择使用的“设计模式”时要关注程序整体的思路而不是过分的细节。因为“设计模式”是将项目的解决方案整体抽象出来,在类和对象的层次进行描述的。

“设计模式”的核心思想是“通过增加抽象层,把变化的部分从那些不变的部分中分离出来”。在接下来的所有“设计模式速谈”系列文章中,针对每一种“设计模式”,我们会结合相应的简单例子来帮助大家理解“设计模式”在实际工程中的应用,而不是单纯的理论概念。

首先需要知道的是,所有的设计模式都是建立在以下五种原则之上的:

1. “开.闭”原则(Open Closed Principle,OCP):

软件设计应该对扩展是开放的,对修改是封闭的。OCP 原则可以理解为我们可以对软件系统进行功能上的扩展,但在进行扩展时不应该修改原有的系统代码。

2. 单一职责原则(Single Responsibility Principle, SRP):

就一个类而言,应该有且只有一个引起其变化的原因,变化的方向隐含着类的责任。比如 Modem 类有两个方法,一个负责管理连接,一个负责通讯,则这个类便违背了 SRP 原则。Modem 类应该只用来负责通讯。所谓的“职责”可以理解为一个类所包含的功能范畴,这些功能应该全部属于同一个范畴之内。比如 Modem 类负责通讯,可以有调整通讯协议调整通讯方式等方法,而管理连接则不应该属于通讯的范畴,即不应该属于 Modem 类所具有的功能。

3. 里氏替换原则(Liskov Substitution Principle, LSP):

“继承”必须确保基类所拥有的性质在子类中仍然成立,即 “is-a” 的关系。LSP 原则是继承的“基石”,类之间的父子关系只有满足 LSP 原则时,才能称谓是继承关系。而确保 LSP 原则的方法是:只有当子类能够“替换”掉其基类,并且系统功能不受影响时,基类才能够被复用,子类也能够在基类的基础上增加新的功能。例如:父类-鸟,子类-企鹅,则这个关系便违背了 LSP 原则,因为父类的鸟有“飞”这个方法,但是企鹅并不会飞。

4. 依赖倒置原则(Dependence Inversion Principle, DIP):

高层模块(稳定)不应该依赖低层模块(易变),二者都应该依赖于抽象(稳定)。抽象不应该依赖于实现细节,实现细节应该依赖于抽象。

5. 接口隔离原则(Interface Segregation Principle, ISP):

多个和客户相关的接口要好于一个通用的接口,接口应该小而完备。这个原则很好理解,永远不要尝试去开发一个“ 通用”的接口,根据不同的使用者将功能独立出来是更好的选择。即一个类应该只对应一个使用者,按照功能或者属性尽量的去划分。

除了上述五大原则,还有以下几点需要注意:

1. 优先使用对象组合,而不是类继承:

类继承通常为白箱复用,组合通常为黑箱复用。继承在某种程度上破坏了封装性,子类父类耦合度高。而对象组合只要求被组合对象拥有良好定义的接口,耦合度较低。

2. 封装变化点:

使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生影响,从而实现层次之间的松耦合。比如 C++ 中常采用的 Pimpl 模式。

3. 针对接口编程,而不是针对实现编程:

  • 不将变量类型声明为某个特定的具体类(通常指业务类型,比如 Rect、Circle),而是应该声明为某个接口(比如 Shape);
  • 客户程序无需获知对象的具体类型,只需要知道对象所具有的的接口;
  • 减少系统中各部分的依赖关系,从而实现“高内聚,低耦合”的类型设计方案;

这里再多说一句,设计模式根据应用的角度被分为“创建型”、“结构型”以及“行为型”三种类型。“创建型” 可以理解为用来创建对象的模式,这些模式抽象了类实例化的过程。“结构型”讨论的是类和对象间的结构,这些模式实现了不同的类继承关系。而“行为型”则着力解决的是类实体之间的通讯关系,即某一具体的控制流程。

接下来,我们将会针对几种常用的设计模式进行逐一讲解。




评论 | Comments


Loading ...