面向对象设计原则
![面向对象设计原则](https://static001.geekbang.org/infoq/df/df74f94e816f4628cc0a1c2bcbdc5075.jpeg)
如何同时提高一个软件系统的可维护行和可复用性,是面向对象设计要解决的核心问题。也是老板们关心的问题,如何用最低的人力、物力解决复杂系统问题。本文从最基本的对象设计出发,描述面向对象设计的原则。总体分为:
![](https://static001.geekbang.org/infoq/dd/dd0d84de3b932ca0652d8a7108f887d1.png)
下面分别描述:
1、开闭原则
开闭原则是面向对象可复用设计的第一块基石,缩写为“OCP”。开闭原则讲的是:一个软件实体应当对扩展开放,对修改关闭。也就是说,在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。
所有的软件系统都有一个共同的特性,即对它们的需求都会随着时间的推移而发生变化。当软件系统面临新的需求时,系统的设计必须是稳定的。那么,如何做到“开闭”呢?
抽象化是关键。解决问题的关键在于抽象化。在Java语音里,可以给出一个或多个抽象Java类或接口,规定出所有的具体类必须提供的方法,作为系统设计的抽象层。这个抽象层预见了所有的可能扩展,因此,在任何扩展情况下都不会改变。同时,从抽象层扩展出的一个或多个新的具体类可以改变系统行为。如下图:
![](https://static001.geekbang.org/infoq/09/09b1fc13f930cb1c7995ff45a3c015ca.png)
2、里氏替换原则
从开闭原则总可以看出面向对象设计的重要原则是创建抽象化,并且从抽象化导出具体化。具体化可以导出不同的版本,每一个版本都给出不同的实现。从抽象化到具体化要使用继承关系。里氏替换原则一样,也要使用继承关系。
里氏替换原则表达的是:一个软件实体如果使用的是一个基类的话,那么一定适用于其子类,而且并不能察觉出基类对象和子类对象的区别。简言之:任何基类可以出现的地方,子类一定可以出现。
3、依赖倒置原则
实现开闭原则的关键是抽象化,并且从抽象的基类导出具体类的实现。依赖倒置原则是开闭原则的主要机制。
依赖倒置原则讲的是:要依赖于抽象,不要依赖于具体。
以抽象的方式耦合是依赖倒置原则的关键。下面以模板方法模式为例,讲述依赖倒置原则的应用。
![](https://static001.geekbang.org/infoq/cb/cb7422d3515820b62b2ff13f978042c8.png)
在模板方法模式里面,有一个抽象类定义主要逻辑声明,具体类实现抽象类的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而形成不同的实现具体子类。具体子类不影响抽象类的声明,而抽象声明的改变则会导致具体逻辑的改变。模板方法是依赖倒置原则的具体体现。
4、接口隔离原则
接口隔离原则讲的是:使用多个专门的接口要比使用单一的接口好。换言之,一个类对另外一个类的依赖性应当是建立在最小的接口上。我们从Java语音的接口来看,接口隔离原则就是为同一个角色提供宽、窄不同的接口,已应对不同的客户端。以下图为例:
![](https://static001.geekbang.org/infoq/02/02c9b1e2001c7cce8e619aa3a591e9f5.png)
在上图中,有一个接口Service以及两个不同的客户端。这两个客户端需要的服务都是有些不同的,因此系统分别为他们提供了两个不同的java接口,即IService1、IService2。很显然,每一个java接口都仅仅将客户端需要的方法暴露给客户端,没有将客户不需要的方法暴露。
5、单一职责原则
单一职责原则讲的是:不要存在多于一个导致类变更的原因。通俗地说,即一个类只负责一项职责。如果职责过多,代码就会臃肿,可读性更差,也更难以维护。其实上单一职责原则和接口隔离原则有一定的关系,接口隔离以后,职责就单一了,实现这个接口的类的职责自然也就单一了。但是接口隔离关注的是抽象层,单一职责关注的是两者兼而有之,偏重于实现。
评论