《(49)--14-4 面向对象设计原则 单一职责原则 面向对象与UML.pdf》由会员分享,可在线阅读,更多相关《(49)--14-4 面向对象设计原则 单一职责原则 面向对象与UML.pdf(21页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 面向对象与面向对象与UML Object-Oriented and UML 面向对象设计原则面向对象设计原则 Object-Oriented Design Principles -3-3-面向对象的基本设计原则面向对象的基本设计原则(1)LSP:Liskov(里氏里氏)替换原则替换原则 Liskov Substitution Principle(2)OCP:开放:开放-封闭原则封闭原则 Open-Close Principle(3)SRP:单一职责原则:单一职责原则 Single Responsibility Principle(4)ISP:接口隔离原则:接口隔离原则 Interface S
2、egregation Principle (5)DIP:依赖倒置原则:依赖倒置原则 Dependency Inversion Principle(6)CARP:组合组合/聚合复用原则聚合复用原则 Composite/Aggregate Reuse Principle(7)LOD(LKP):迪米特法则迪米特法则(最少知道原则最少知道原则)Law of Demeter(Least Knowledge Principle)SRP(Single Responsibility Principle)单一职责原则单一职责原则 一个优良的系统设计,强调模块间保持一个优良的系统设计,强调模块间保持低耦合、高内聚
3、低耦合、高内聚的关系的关系。在面在面向对象设计中这条规则同样适用向对象设计中这条规则同样适用:单一职责原则(单一职责原则(SRPSRP,Single Single Responsibility PrincipleResponsibility Principle)。)。单一职责,强调的是职责的分离单一职责,强调的是职责的分离。在某种程度上对职责的理解,构成在某种程度上对职责的理解,构成了不同类之间耦合关系的设计关键,因此单一职责原则或多或少成为了不同类之间耦合关系的设计关键,因此单一职责原则或多或少成为设计过程中一个必须考虑的基础性原则。设计过程中一个必须考虑的基础性原则。单一职责原则定义单一职
4、责原则定义 SRP单一职责原则的陈述单一职责原则的陈述 就一个类而言,应该仅有一个引起它变化的原因。就一个类而言,应该仅有一个引起它变化的原因。对于单个类而言,最核心的工作就是其职责分配过程。对于单个类而言,最核心的工作就是其职责分配过程。SRP单一职责原则是指导类的职责分配的最基本原则,是单一职责原则是指导类的职责分配的最基本原则,是面向对象设计中最重要的基本原则之一。面向对象设计中最重要的基本原则之一。类设计应遵从类设计应遵从SRP的原因的原因 类类的职责定义为“变化的原因”,每个职责都是变化的一个轴线;的职责定义为“变化的原因”,每个职责都是变化的一个轴线;当需求变化时,该变化会反映为类
5、的职责的变化。当需求变化时,该变化会反映为类的职责的变化。如果一个类承担了多于一个的职责,那么引起它变化的原因就会如果一个类承担了多于一个的职责,那么引起它变化的原因就会有多个,从而造成类内部的频繁变化。有多个,从而造成类内部的频繁变化。不同的职责耦合在同一个类中,一个职责的变化可能会影响其它不同的职责耦合在同一个类中,一个职责的变化可能会影响其它职责。职责。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。到意想不到的破坏。-多职责将导致脆弱性的臭味。多职责将导致脆弱性的臭味。因此,类设计应遵从因此,类设计应遵从SRP,应建
6、立高内聚的类。,应建立高内聚的类。SRP单一职责原则单一职责原则本质本质 SRP体现了体现了内聚性(内聚性(Cohesion)内聚性:一个模块的组成元素之间的内聚性:一个模块的组成元素之间的功能相关性功能相关性。模块设计应遵循模块设计应遵循高内聚高内聚的设计原则。的设计原则。功能内聚功能内聚是内聚度最高的一种内聚形式,是指模块内所有元素共是内聚度最高的一种内聚形式,是指模块内所有元素共同完成一个功能,缺一不可,模块不能再被分割。同完成一个功能,缺一不可,模块不能再被分割。类设计,也应保持高内聚,即达到类设计,也应保持高内聚,即达到功能内聚功能内聚。实例实例1-Rectangle类类 Recta
7、ngle类具有类具有两个职责两个职责:(1)计算矩形面积的数学模型)计算矩形面积的数学模型 perimeter()-计算周长的功能计算周长的功能 area()-计算面积的功能计算面积的功能 (2)将矩形在一个图形设备上描述出来)将矩形在一个图形设备上描述出来 draw()-绘制矩形的功能绘制矩形的功能 full()-填充矩形的功能填充矩形的功能 Rectangle类违反了类违反了SRP,具有两个职能,具有两个职能计算面积和绘制矩形计算面积和绘制矩形 计算机与控制工程学院计算机与控制工程学院 郭艳燕郭艳燕 实例实例1-违反违反SRP的案例的案例 Rectangle类会因为两方面的原因而变化:类会
8、因为两方面的原因而变化:计算几何方面计算几何方面的原因和的原因和用户界面设计方面用户界面设计方面的原因。其中一个发生变化后,必须修改的原因。其中一个发生变化后,必须修改Rectangle类,而这种修改则可能导致另一个应用程序出错。类,而这种修改则可能导致另一个应用程序出错。除此之外,违反除此之外,违反SRP还会带来物理依赖的缺点。还会带来物理依赖的缺点。两个不同的应用都使用两个不同的应用都使用Rectangle类,有两种职责。类,有两种职责。使用使用Rectangle类类中的中的perimeter()和和area()方法。方法。使用使用Rectangle类中的类中的draw()和和full()
9、方法。方法。GUILibaray 的修改会影响的修改会影响Rectangle类,从而影响数学应用类,从而影响数学应用程序和绘图程序,而数学应用程序其实上与程序和绘图程序,而数学应用程序其实上与GUIlibrary无关。无关。实例实例1-违反违反SRP的案例的案例 对对SRP的违反将导致两个方面的问题的违反将导致两个方面的问题:(1)包含不必要的代码)包含不必要的代码 一个应用可能希望使用一个应用可能希望使用Retangle类计算矩形的面积,但是却被迫将类计算矩形的面积,但是却被迫将绘制矩形相关的代码也包含绘制矩形相关的代码也包含进来。进来。(2)一些逻辑上毫无关联的原因可能导致应用失败)一些逻
10、辑上毫无关联的原因可能导致应用失败 如果如果绘图程序绘图程序的需求发生了变化,从而对的需求发生了变化,从而对Rectangle类进行了修改。类进行了修改。但是这样的变化居然会要求我们重新构建、测试以及部署但是这样的变化居然会要求我们重新构建、测试以及部署数学应用数学应用程序程序,否则其将莫名其妙的失败。,否则其将莫名其妙的失败。-11-11-实例实例1 1-解决方案解决方案-遵循遵循SRP 增加新的类,使得每个类仅有一个职责。增加新的类,使得每个类仅有一个职责。Rectangle类中的类中的perimeter()和和area()方方法,仅负责法,仅负责计算几何方计算几何方面中的职责面中的职责。
11、GUIRectangle类中的类中的draw()和和full()方法方法,仅负责仅负责用户界面设计方面的职责用户界面设计方面的职责。各自类的修改不各自类的修改不会影响各自对应会影响各自对应的应用程序。的应用程序。GUILibaray 的修的修改不会影响数学应改不会影响数学应用程序。用程序。实例实例2-违反违反SRP的案例的案例 某基于某基于Java的的C/S系统的“登录功能”通过如下登录类系统的“登录功能”通过如下登录类(Login)实现:实现::void:boolean:Connection:void:void:voidmain(String args)String userPassword
12、)findUser(String userName,getConnection()validate()display()init()+LoginLogin类具备多种职责:类具备多种职责:(1)应用程序调用职责应用程序调用职责(2)用户登录图形界面职责用户登录图形界面职责(3)身份验证业务处理职责身份验证业务处理职责(4)数据库连接处理职责数据库连接处理职责 不良的设计:违反了单一职责不良的设计:违反了单一职责原则。原则。实例实例2 2-解决方案解决方案-遵循遵循SRP:voidmain(String args)+MainClass:ConnectiongetConnection()+DBUti
13、l:boolean String userPassword)findUser(String userName,+:DBUtildb-UserDAO:void:void:voidvalidate()display()init()+:UserDAOdao-LoginForm使用使用SRP单一职责原则对其进行重构后类图。单一职责原则对其进行重构后类图。(1)应用程序调用职责应用程序调用职责(2)用户登录图形界面职责用户登录图形界面职责(3)身份验证业务处理职责身份验证业务处理职责(4)数据库连接处理职责数据库连接处理职责 SRP单一职责原则总结单一职责原则总结 好的设计方案是将类的职责分离出来,从而
14、保持每一个类处理一类职责,好的设计方案是将类的职责分离出来,从而保持每一个类处理一类职责,从而满足从而满足SRP。SRP是一种非常简单的原则,但却是最难正确应用的原则之一。是一种非常简单的原则,但却是最难正确应用的原则之一。注意:注意:SRP明确地告诉设计人员应保持类职责的内聚性。但单一职责并明确地告诉设计人员应保持类职责的内聚性。但单一职责并不等同于说类只有一个职责,这种职责过于单一的类必将加大系统的耦不等同于说类只有一个职责,这种职责过于单一的类必将加大系统的耦合程度。因此,要合理评估类的职责,合程度。因此,要合理评估类的职责,结合业务场景考虑职责的相关性结合业务场景考虑职责的相关性,从而
15、将不相关的职责互相分离,达到从而将不相关的职责互相分离,达到SRP所要求的类的内聚性所要求的类的内聚性。实例实例3-Modem接口接口 在在SRP中,把职责定义为“变化的原因”中,把职责定义为“变化的原因”(a reason for change)。如果你能够想到多于一个的动机去改变类,那么这个类就具有多于一个如果你能够想到多于一个的动机去改变类,那么这个类就具有多于一个的职责。有时,我们很难注意到这一点。我们习惯于以组的形式去考虑的职责。有时,我们很难注意到这一点。我们习惯于以组的形式去考虑职责。职责。class Modem public:virtual void dail(char*pno
16、)=0;virtual void hangup()=0;virtual void send(char c)=0;virtual void recv()=0;Modem接口合理吗?接口合理吗?Modem确实具有声明的确实具有声明的4个函数的功个函数的功能。能。但显示出了两个职责但显示出了两个职责(1)连接管理连接管理(dial+hangUp)(2)数据通信数据通信(send+recv)实例实例3-Modem接口接口 这两个职责应该被分离开么?依赖于应用程序的变化,按照实际情况来这两个职责应该被分离开么?依赖于应用程序的变化,按照实际情况来决定。决定。Modem例子可能存在两种变化的方式例子可能存
17、在两种变化的方式 (1)连接和通信可能独立变化连接和通信可能独立变化 如果应用程序的变化会影响连接管理,不会影响通信管理,在这种情况下,如果应用程序的变化会影响连接管理,不会影响通信管理,在这种情况下,这两个职责应该被分离,这样做会避免这两个职责耦合在一起。否则设这两个职责应该被分离,这样做会避免这两个职责耦合在一起。否则设计就具有“僵化”的臭味计就具有“僵化”的臭味。(2)连接和通信同时变化)连接和通信同时变化 如果应用程序的变化总是导致这两方面职责同时变化,那么就不必分离他如果应用程序的变化总是导致这两方面职责同时变化,那么就不必分离他们。实际上,分离它们就会具有“不必要的复杂性”的臭味。
18、们。实际上,分离它们就会具有“不必要的复杂性”的臭味。职责是“变化的原因”。职责是“变化的原因”。实例实例3-Modem接口接口职责分离后设计方案职责分离后设计方案 单一职责原则的好处单一职责原则的好处 降低类的复杂性降低类的复杂性,类的职责定义明确,可读性提高。,类的职责定义明确,可读性提高。有利于实现类的高内聚。有利于实现类的高内聚。降低变更引起的风险。降低变更引起的风险。变更是必不可少的,如果类的单一职责做得好,变更是必不可少的,如果类的单一职责做得好,一个类的修改只对它的使用者有影响,对系统的扩展性、维护性有较一个类的修改只对它的使用者有影响,对系统的扩展性、维护性有较大的帮助。大的帮
19、助。小结小结 如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其它职责的能力。这种耦合会导的变化可能会削弱或者抑制这个类完成其它职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。如果能想到多于一个动机去改变一个类,那么这个类就具有多于一个的如果能想到多于一个动机去改变一个类,那么这个类就具有多于一个的职责,就应该考虑类的职责分离。职责,就应该考虑类的职责分离。软件设计真正要做的许多内容,就是发现职责并
20、把那些职责相互分离。软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。SRP是所有原则中最简单、也是最难运用的。其余原则会以这样或那是所有原则中最简单、也是最难运用的。其余原则会以这样或那样的方式回到这个问题上。样的方式回到这个问题上。单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口类或类设计的是否好,但“职责”和“变化原因”都是不来衡量接口类或类设计的是否好,但“职责”和“变化原因”都是不可度量的,因项目而异,依环境而异。可度量的,因项目而异,依环境而异。单一职责原则很难在项目中得到体现,因为需要考虑工期、成本、人单一职责原则很难在项目中得到体现,因为需要考虑工期、成本、人员技术水平、硬件情况甚至项目之外的因素。员技术水平、硬件情况甚至项目之外的因素。建议建议 接口接口一定做到单一职责,类的设计尽量做到只有一个原因引起变化。一定做到单一职责,类的设计尽量做到只有一个原因引起变化。本章小结本章小结