设计模式简介

相信你只要接触过软件编程,那么一定听说过设计模式。所谓设计模式,是为解决特定问题,一套通用的、可重用的软件设计方案。我们通常所说的设计模式,是针对面向对象语言而言。对于每一位使用面向对象语言的从业者,在学习完该语言的基础知识后,也一定了解如何编写面向对象的程序。但是,面向对象究竟有什么好处,我们又应该如何灵活运用面向对象来设计程序呢?

1. 面向对象

面向对象出现之前,程序是面向过程的。两者在软件设计上有着很大的不同。
面向过程,我们首要思考逻辑过程是什么,如何设计这个过程。
面向对象,首先要考虑的是有哪些对象,对象有什么行为,最后才是行为的逻辑。

面向对象的可以让你程序的设计和真实世界更为契合。这会带来如下优点:

  1. 现实世界有千百年积累下来数以万亿计的优秀设计,无论是具体的机械设备,还是方法论,或者工程理论。我们都可以拿来作为软件设计的参考。
  2. 面向对象开发出的软件,让其他开发者更容易理解。我们每个人都熟知我们所生活的世界。面向对象可以让枯燥的代码更加鲜活,甚至凭你的经验,也能猜出对象的某个行为应该是怎样的逻辑。

夸了半天面向对象,你可能会想,面向对象确实不错,我所使用的语言也是面向对象的,那我编写的程序天然也就拥有了面向对象的优点。这种想法是错误的。语言仅仅是个工具,而面向对象编程是一种思维。如果对面向对象编程没有深入理解,那么你写出的程序,也只是披着面向对象的外衣而已。此外,即使你充分理解了面向对象的思维,也不一定能够灵活运用面向对象解决问题。那么,此时就轮到设计模式出场了!

2. 设计模式来自哪里

设计模式不是凭空想出来的。作为通用的设计方式,设计模式是跨语言的。要想做到跨语言,那么它的根基一定是万物都要遵守的规律。设计模式来源于真实世界,前辈们通过不断地归纳总结、实践,将一些已经存在的设计理论运用于软件领域,并很好地解决了软件设计上的问题。最终呈现给我们这些丰富的设计模式。
当我们学习设计模式之后,就可以深刻体会到为什么设计模式来源于真实世界。这里我先举个例子,比如订阅者模式。一听名字你一定可以映射到现实生活中某些类似的方式,比如订报纸,订牛奶。订的人就是订阅者,送的人就是发布者。发布订阅的核心思想,再加上软件的特性,就构成了订阅者模式。

3. 设计原则

那么使用设计模式能为软件开发带来什么好处呢?这要从设计模式的设计原则说起,一般来说有6大原则,如下:

  1. 单一职责原则
    顾名思义,一个类最好只有一个职责。这样的好处是引起类发生变化的原因会很少。我们开发新需求的时候,就会很少去修改这个类。而且职责越单一也越容易被复用。
  2. 开闭原则
    软件应该对扩展开放,对修改关闭。通俗易懂的说,就是你的软件不能因为加功能,就不断地修改已有的类。而是应该通过增加类,以插拔的方式来实现。举个例子,Macbook的变压器插头是可以替换的,如果说某一天插口的标准换了,那么苹果只需要开发一个新的插头就好了,而不需要重新开发整个变压器。开闭原则确保了代码最大程度的可复用性。并且确保了成熟代码的稳定性。
    图片描述
  3. 里氏代换原则
    子类型可以替换掉自己的父类。这意味着我们编写的软件,所有使用父类的地方,都可以替换为子类对象,而程序的行为不会发生改变。通过里氏代换原则,我们可以实现开闭原则,通过增加子类实现新的功能,而不是不断地修改父类。在需要的地方则用子类代替父类。如何实现里氏代换原则呢?首先子类不能重写父类的非抽象方法,一旦重写了非抽象方法,就会改变父类的行为。但是子类可以增加自己的方法和属性,以此达到扩展的目的。
  4. 依赖倒转原则
    简单说就是应该依赖接口,而不是实现。也就是我们常说的面向接口编程。这样类和类之间就不会直接依赖,从而能够实现开闭原则。类依赖接口,当需要扩展的时候我们可以替换实现。
  5. 迪米特法则
    也称为最少知道原则。如果两个类没有必要直接通信,那么两个类就没有必要相互作用。可以通过第三方来间接调用。类之间的耦合度越弱,越容易被复用。在弱耦合的关系中,一个类的修改,造成的影响会很小。所以我们在做设计的时候需要考虑哪些应该对外暴露,哪些应该封装起来。不同功能模块间的调用,应该由更为高层的类来实现,从而屏蔽掉底层的实现。
  6. 接口隔离原则
    接口隔离原则指导你如何设计接口。不要让接口变得臃肿,而是应该把接口按照行为不同细拆。比如你要生产一把可以拼刺刀的步枪,那它应该实现两个接口,刀的接口和枪的接口。而不是使用一个接口覆盖所有刀和枪的所有行为。这样不同的接口可以组合使用。而且如果你只需要刀或者枪的行为,可以单独实现需要的接口, 不需要实现一个大而全的接口,从而去实现很多用不到的方法。

如果你的代码满足以上设计原则,就会更为健壮、灵活和优雅。那么如何做到上面这些原则呢?很简单,学习好设计模式,灵活运用设计模式解决你的问题。

4. 为什么要学习设计模式

前面已经给出了设计模式的定义----为解决特定的问题,一套通用的、可重用的软件设计方案。我们面对的问题不一样,需要选择不同的设计模式来解决问题。

这就好比木匠有 20 种工具,分别用于做不同的事情。而设计模式就是软件设计的工具,根据你遇到的问题不同,供你选择使用。而学习设计模式的目的,就是让你熟知工具的样子,工具能够做什么事情,解决什么样的问题。当你再遇到设计问题时,自然就会想到采用什么设计模式来解决。

设计模式有多厉害呢?我可以讲一个亲身经历,曾经我有一位同事写了一段代码来完成一个功能。code review时,我和他说你可以看一下设计模式,这段代码使用XX模式来实现会更为的优雅。两天后他找到我说:“设计模式太厉害了!感觉我前几年代码都白写了!” 你不要觉得夸张,他的这个感觉,也是我初学设计模式后的感觉----原来程序还可以这么写!以前我们解决问题的工具是锤子、斧子,而现在全都是机械化工具。设计模式就是这么神奇的东西。

5. 学习基础

只要你掌握了一门面向对象的编程语言,并且熟悉面向对象的相关知识即可。当然如果有一定的编程基础更好。此外需要了解一些UML相关的知识,方便理解类图。

6. 小结

本节从面向对象讲起,讲解了什么是设计模式,程序设计的原则有哪些,为什么要学习设计模式。设计模式是写好程序的根基。我们常常提到代码要高内聚、松耦合,代码要健壮等等。这些优秀代码的特性,全都来自于设计模式。足以见得设计模式的重要性。本小结内容比较多,总结如下:
图片描述