一、面向对象设计原则
1.1、概述
如何同时提高一个软件系统的可维护性和可复用性是面向对象设计需要解决的核心问题之一。在面向对象设计中,可维护性的复用是以设计原则为基础的。每一个原则都蕴含一些面向对象设计得思想,可以从不同的角度提升一个软件系统结构的设计水平。
最常见的7种面向对象设计原则如下:
设计原则名称 | 定义 |
单一职责原则(Single Responsibility Principle,SRP) | 一个类只负责一个功能领域中的相应职责 |
开闭原则(Open-Closed Principle,OCP) | 软件实体应对扩展开放,而对修改关闭 |
里氏代换原则(Liskov Subsitution Principle,LSP) | 所有引用基类对象的地方能够透明地使用其子类的对象 |
依赖倒转原则(Dependence Inversion Principle,DIP) | 抽象不应该依赖于细节,细节应该依赖于抽象 |
接口隔离原则(Interface Segregation Principle,ISP) | 使用多个专门的接口,而不使用单一的总接口 |
合成复用原则(Composite Reuse Principle,CRP) | 尽量使用对象组合,而不是继承来达到复用的目的 |
迪米特法则(Law of Demeter,LoD) | 一个软件实体应当尽可能少地与其他实体发生相互作用 |
1.2、单一职责原则
单一职责原则是实现高内聚、低耦合的指导方针,是最简单的面向对象设计原则,它用于控制类的粒度大小,定义如下:
一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
一个类(大到模块,小到方法)承担的责任越多,它被复用的可能性就越小,而且一个类承担的职责越多,就相当于把这些职责都耦合在一起,当其中一整个职责变化时,可能会引起其他职责的运作,因此就要讲这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果是多个职责总是同时发生变化则可以将它们封装在同一类中。
示例分析:
Sunny软件公司开发人员针对某CRM(Customer Relationship Management,客户关系管理)系统中客户信息图形统计模块提出了如图所示初始设计方案:
在图中,CustomerDataChart类中的方法说明如下:getConnection()方法用于连接数据库,findCustomers()用于查询所有的客户信息,createChart()用于创建图表,displayChart()用于显示图表。
现使用单一职责原则对其进行重构:
初始方案中CustomerDataChart类承担的职责既有对数据库的操作,又包含图标生成和显示的方法,若其他类中也需要连接数据库或者使用findCustomers()方法查询客户信息,则很难实现代码的复用。引起CustomerDataChart类变化的原因不止一个,违背了单一职责原则,因此需对其进行拆分,如下:
- DBUtil:负责连接数据库,包含数据库连接方法getConnection();
- CustomerDAO:负责数据库中的Customer表,包含对Customer表的增删改查等方法,如图中的findCustomers();
- CustomerDataChart:负责图表的生成和现实,包含方法createChart()和displayChart()。
重构后的UML图如下:
1.3、开闭原则
开闭原则是面向对象的可复用设计的第一块基石,是最重要的面向对象设计原则,定义如下:
一个软件实体应当对扩展开放,对关闭修改。即软件实体应尽量在不修改原有代码的情况下进行扩展。
在开闭原则的定义中,软件实体可以指一个软件模块、一个由多个类组成的局部结构或者一个独立的类。
软件的需求会随着时间的推移发生变化,当系统软件面