Open-Close原则
是一个愿景性质的原则,如果系统能够达到Open-Close原则描述的情形就比较理想了,对扩展开放、对修改关闭,即,不修改原有代码即可完成对系统的扩展。
实现Open-Closed原则,抽象化是关键。
抽象层,因为抽象所以稳定。不变应万变,不用修改,满足Open-Closed原则的Closed一头。
抽象层的具体实现层可以满足扩展要求,满足Open-Closed原则的Open一头。
Open-Closed原则还可表述为“对可变性的封装”原则。“找到一个系统的可变因素,将它封装起来。”
一个可变性因素,不应该被散落在各个角落,而应该被封装到一个对象中。
一种可变性因素,不应该与另一种可变性因素混和在一起,而应各自独立开。
但,单从原则本身来说,它并没有告诉我们如何才能够让系统满足这个原则。
里氏代换原则
指导我们如何去构建一个extends(继承、派生)结构。
子类与父类的关系必须是is-A,即,子类必须在任何场合都敢于大声宣称自己起码(至少)是一个父类。比如,假设某类结构,“男人”、“女人”从“人”派生出来,看起来就是满足里氏代换原则的,因为无论“男人”还是“女人”,在任何场合都是“人”。这个原则大多数情况下,可以用现实世界中的概念来思考,但软件世界与显示世界毕竟有区别,比如,书中的例子,“正方形是不是矩形”问题。
此外,很多问题需要利用OO核心思想来灵活考虑,还是书中的例子(我只说大概意思,可能与书中描述存在差异),一个类结构,“职工、普通职员、项目经理、科长、部长……”,从“员工”类派生出来,从一般概念来看还不错,职工和部长都是员工嘛,但这里隐含问题,现实世界中,普通职员可能变成项目经理,但软件世界中,普通职员和项目经理被规划成两个类了,于是一个普通职员instance是很难变成项目经理instance的,这说明我们把显示世界映射为软件世界时,出现了问题。更加合理的做法是,把这些职务(角色)抽象出来,比如叫做“职务”类(interface/abstract class),所有职务从其派生,员工类、职务类是关联关系,任何一个员工实例都一个职务实例作为它的属性,这样就对了,员工的职务是可以变化的。实现这个重构的依据,是OO中的封装变化思想,以及从中演化出来的依赖倒换原则、合成/聚合复用原则。
但凡涉及到extends结构的设计模式都符合着里氏代换原则:
策略模式:一组算法,把他们封装成对象,使之可以互换(满足同一接口,即都is-A这个接口)。
合成模式:Leaf和Composite都is-A Component,于是才可能方便地层层嵌套。
代理模式:Proxy与RealSubject都is-A父类Subject,于是可以插入代理,完成附加功能。
……
依赖倒换原则
很具体地指导我们对抽象类(接口)、实现类的使用。
依赖于抽象的实体(interface/abstract class),才能够更具有可插入性(但凡实现既有接口的实现类实例都可以在依赖此接口的地方以此接口实例的角色插入进来),更容易满足Open-Close原则(抽象的层次不变化、实现的层次由于使用不同的类来封装不同的变化,于是可以在增加新类作为扩展的同时不需要修改已有实现类)。
接口隔离原则
这个原则比较孤立,也是从OO封装变化思想演化出来的,要将变化封装到最“贴身”。比如,A/B接口可能在大多数情况下都由同一个实现类提供,但某些情况下,B接口都有些实现类是没有意义的,这时候就需要把A/B分开作为两个接口,某些类实现全部A/B接口、某些类仅实现A接口。A/B单独变化,于是把A/B单独封装,接口隔离。
合成/聚合复用原则
与里氏代换原则关系较为紧密,里氏代换原则告诉我们什么情况下使用extends,在不满足里氏代换原则时,还想达到重用的目的,就引出合成/聚合复用原则。上文中,员工与职务的例子,来说明这个事儿就比较合适。
从复用角度来说:“合成/聚合复用”比“继承”复用灵活。前者是动态复用(因而具有可插入性)、后者是静态复用(编译时就固定了复用关系),而且后者的复用有“不支持多重继承”的限制。
迪米特法则
用于解开类之间的不必要的耦合。“不要与陌生人说话”。说起来容易,实际操作的时候很可能出现些无所适从的问题,而解开类之间的耦合是比较重要的,目前我们设计类的时候,增加属性、增加对其他类的调用都比较随意,不太好。
迪米特法则要求:一个对象应当对其他对象有尽可能少的了解。几种其他的表述:只与你直接的朋友通信、不要跟“陌生人”说话(冯远征?)
每个软件单位对其他单位都具有最少的知识,而且局限于那些与本单位密切相关的软件单位。
狭义迪米特法则-规定了谁是Friends、谁是Stranger。Friends圈子包括:
当前对象自身(this)、Instance field(如果field是Map、List等容器类型,则容器内的对象也是朋友)、当前对象创建的对象(调用其构造方法)、当前对象方法的参数对象。
只跟Friends说话,跟Stranger说的话由Friends转述。
狭义迪米特法则的弊端:传递间接调用的小方法太多!解决办法:遵循依赖倒换原则做些折衷处理,让对象依赖于Stranger的抽象层。虽然没有完全断开耦合,至少降低了耦合。
小结
Open-Close原则是比较总体的要求、是愿景。
实现Open-Close原则的关键,是抽象。
依赖倒换原则就是强调抽象的。
有了抽象层,就要有实现层,实现层无疑要从抽象层extends/implements,实现层/抽象层的关系,要依从里氏代换原则。
很多情况不满足里氏代换原则,又要实现复用,于是引出,合成/聚合复用原则。
两外两个原则是说类之间(接口)关系的。
接口隔离原则,要求类之间的接口更加狭窄,更加确切、更加合身地封装变化。
迪米特法则,要求类之间的接口应该发生在哪些类之间,不应该发生在哪些类之间。帮助我们解开类之间的耦合。
参考文献:
阎宏《Java与模式》
Meilir Page-Jones《UML面向对象设计基础》
分享到:
相关推荐
【学习oo好榜样(设计良品)】 设计良好的软件代码是每个程序员追求的目标,而避免“Bad Smells”(不良代码气味)并进行重构是实现这一目标的重要手段。本篇文章将探讨两个重要的代码质量指标——重复的代码...
面向对象设计原则是软件开发中的一种核心思想,它为创建可维护、可扩展且易于理解的代码提供了指导方针。在本文中,我们将深入探讨这些原则,帮助你更好地理解和应用它们。 1. **单一职责原则(Single ...
面向对象设计原则与设计模式是软件工程领域的重要组成部分,它们为构建高质量、可维护和可扩展的软件系统提供了指导方针。下面将详细阐述面向对象设计原则及其如何促进软件的复用,以及设计模式的概念。 ### 面向...
在面向对象设计中,子类应该能够替换其基类并且保持程序原有的行为不变。违反这一原则可能导致运行时错误或者异常行为,因为子类可能无法完全符合基类所规定的所有行为。 ### 依赖倒置原则(DIP) **定义**:高层...
9. **OO设计**:这部分内容可能涵盖了面向对象设计的整体流程,包括分析结果的转化、类的设计原则、接口设计等。 通过这些课件,学习者可以深入了解面向对象分析与设计的全貌,掌握从需求分析到系统实现的关键步骤...
掌握内聚度和耦合度的概念 掌握面向对象设计原则
面向对象需求分析(OO RES) 面向对象需求分析(Object-Oriented Requirements Engineering,OO RES)是一种基于面向对象技术的需求分析方法。该方法将需求分析过程分为三个主要阶段:问题域分析、需求定义和系统...
高内聚和低耦合是面向对象设计的重要原则之一。 #### 运作(Moving) 这里的“运作”可以理解为面向对象系统中的动态行为,即对象如何响应外部请求,执行其内部方法,与其他对象进行交互。动态行为的设计和实现是...
面向对象设计原则是软件工程领域中的重要组成部分,旨在提高软件系统的可维护性、可扩展性和灵活性。其中,类设计原则尤为关键,它们指导着开发者如何合理地构建类,以适应不断变化的需求。以下是对给定文件中提及的...
3. **编码实现**:按照设计文档编写代码,注意遵循面向对象设计的原则,如单一职责原则、开放封闭原则等。 4. **测试与维护**:完成编码后进行测试,确保系统满足需求。在后期维护过程中,也要遵循面向对象设计的...
面向对象设计原则是软件开发中重要的指导思想,主要用于构建可维护、可扩展且易于理解的代码结构。在面向对象编程(OOP)中,对象是数据和操作这些数据的方法的集合,而设计原则则是为了更好地利用这些特性来构造...
#### 二、面向对象设计原则之FCOI详解 ##### 1. 对象组合(Composition) **定义:** 对象组合是一种通过将其他对象嵌入到一个对象中来实现复用的方法。这种复用机制使得对象能够通过委托给其所包含的对象来获得新...
面向对象(Object-Oriented,简称OO)设计方法是现代软件开发中的核心理念,它源自于...通过学习和实践,我们可以将现实生活中的问题抽象成对象,用面向对象的方式去解决问题,这也是面向对象设计方法的精髓所在。
第一册:《Head First Java》是本完整的面向对象(object-oriented,OO)程序设计和Java的学习指导。 第二册:《HeadFirst设计模式》(中文版)共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计...
而“action.zip”可能包含了一个或多个具体的代码实例,演示了如何在实践中创建和使用Action类,或者展示了面向对象设计的其他相关技术。 学习面向对象编程,首先要理解类和对象的概念。类是创建对象的蓝图,定义了...
在面向对象设计中,UML(Unified Modeling Language)是一种非常重要的工具。UML提供了一种标准化的方法来描述和定义软件系统的结构、行为和关系。使用UML,可以帮助开发人员更好地理解和描述软件系统,并且可以提高...
通过以上六个面向对象设计原则的学习与实践,可以显著提高软件的质量和可维护性,同时也能更好地应对不断变化的需求。这些原则并非孤立存在,而是相互关联、相辅相成的。在实际开发过程中,应根据项目的具体情况灵活...
"OO 面向对象概念通俗说明" OO 面向对象概念通俗说明是指使用通俗的举例让大家知道 OO 的概念。OO 是一种编程方式,它使用对象和类来组织和设计程序。OO 的主要特征包括封装、继承和多态。 在 OO 中,对象是指具有...