OCP --Open-Close Principle 开放封闭原则
指系统应该对扩展是开放的,而对于修改是封闭的。简单的说就是,对可变性封装。可扩展性指,模块的行为功能可以被扩展,在应用需求改变或需要满足新的应用需求时,我们可以让模块以不同的方式工作。不可更改指,这些模块的源代码是不可改动的。任何人都不许修改模块的源代码。
在设计代码的时候要将变化的(或者可能变化的)部分提取出来,和那些不会改变代码分离。这样在以后需求变更的时候,我们就可以增加、修改系统功能,但不需要对已有代码做大幅度的改变。
实现OCP,抽象化是关键。因为抽象所以稳定,以不变应万变,不用修改。OCP还可表述为“对可变性的封装”原则。“找到一个系统的可变因素,将它封装起来。” 实现开放封闭的核心思想就是对抽象编程,而不对具体编程,因为抽象相对稳定。让类依赖于固定的抽象,所以对修改就是封闭的;而通过面向对象的继承和对多态机制,可以实现对抽象体的继承,通过覆写其方法来改变固有行为,实现新的扩展方法,所以对于扩展就是开放的。这是实施开放封闭原则的基本思路,同时这种机制是建立在两个基本的设计原则的基础上,这就是Liskov替换原则和合成/聚合复用原则。
对于违反这一原则的类,必须进行重构来改善,常用于实现的设计模式主要有Template Method模式和Strategy模式。而封装变化,是实现这一原则的重要手段,将经常发生变化的状态封装为一个类。
这个原则理论性更多一点。有人总结了2条经验吧,可以结合代码细细体会。
◆一个可变性因素,不应该被散落在各个角落,而应该被封装到一个对象中。
◆一种可变性因素,不应该与另一种可变性因素混和在一起,而应各自独立开。
LSP--Liskov Substitution Principle里氏代换原则
这个原则主要说明,如何进行继承。先来看看一个比较抽象的概念。如果对于类型S的每一个对象o1,都有一个类型T的对象o2,使对于任意用类型T定义的程序P,将o2替换为o1,P的行为保持不变,则称S为T的一个子类型。这个原则和面向接口编程有点神似。基本的意思就是,子类继承父类的时候,不要扩展父类的方法,只需继承。这样就可以把实现类赋值给抽象类型,其他对象持有抽象类型,调用实现类的方法。子类不扩展父类的方法就是为了,通过父类来操纵子类。
LSP优点:
1、保证系统或子系统有良好的扩展性。只有子类能够完全替换父类,才能保证系统或子系统在运行期内识别子类就可以了,因而使得系统或子系统有了良好的扩展性。
2、实现运行期内绑定,即保证了面向对象多态性的顺利进行。这节省了大量的代码重复或冗余。避免了类似instanceof这样的语句,或者getClass()这样的语句,这些语句是面向对象所忌讳的。
3、有利于实现契约式编程。契约式编程有利于系统的分析和设计,指我们在分析和设计的时候,定义好系统的接口,然后再编码的时候实现这些接口即可。在父类里定义好子类需要实现的功能,而子类只要实现这些功能即可。
使用LSP注意点:
1、此原则和OCP的作用有点类似,其实这些面向对象的基本原则就2条:1:面向接口编程,而不是面向实现;2:用组合而不主张用继承
2、LSP是保证OCP的重要原则
3、这些基本的原则在实现方法上也有个共同层次,就是使用中间接口层,以此来达到类对象的低偶合,也就是抽象偶合!
4、派生类的退化函数:派生类的某些函数退化(变得没有用处),Base的使用者不知道不能调用,会导致替换违规。在派生类中存在退化函数并不总是表示违反了LSP,但是当存在这种情况时,应该引起注意。
5、从派生类抛出异常:如果在派生类的方法中添加了其基类不会抛出的异常。如果基类的使用者不期望这些异常,那么把他们添加到派生类的方法中就可以能会导致不可替换性。
DIP -- Dependence Inversion Principle 依赖倒换原则
先摘录DIP的定义,很定义很抽象
1、高层模块不应该依赖于底层模块,二者都应该依赖于抽象
2、抽象不应该依赖于细节,细节应该依赖于抽象
二、关于高层模块与底层模块
高层模块是系统不经常发生变化的部分,是一个系统区别于其它系统的重要标志,也是直接面向客户的部分,它包含了系统的策略选择与业务模型。
低层模块是系统中经常发生变化的部分,是系统的实现,是用于驱动系统工作的,它不是(直接)面向客户的。
三、违反DIP原则的后果
DIP原则其实强调的是:不要让不经常发生变化的部分去依赖于经常发生变化的部分。因为一旦经常发生变化的那部分发生了变化,那不经常发生变化的那 部分也要随之变化。这是不合理的设计。更坏的情况是,违反DIP的设计会使你的高层模块很难在不同的场合在被重用,因为此时高层模块的工作是依赖于底层模 块的,这种依赖性使高层模块很难独立开来。
四、依赖抽象与接口所有权的倒置
高层模块与低层模块都应该依赖于抽象,为什么这样说?这是因为抽象的东西不同于具体的东西,抽象的东西发生变化的频率要低,让高层模块与底层模块去 依赖于一个比较的稳定的东西比去依赖一个经常发生变化的东西的好处是显而易见的。表现在代码中,就是多使用接口与抽象类,而少使用具体的实现类。(这样说 可能有点不合适,如果一个具体类不经常发生变化,那完全可以让高层模块去依赖于它)。
面向对象的设计中,提倡“面向接口”的编程,在某种程度上,接口与一个抽象类是一样的。面向接口的编程其实就是利用了抽象将高层模块(如一个类的调用者)与具体的被操作者(如一个具体类)隔离开来,从而使具体类在发生变化时不致于对调用者产生影响。
为了使底层模块的修改不影响高层模块,我们在设计时应该采用面向接口的编程方法,让高层与底层都去依赖接口(抽象),但是接口是由谁来声明呢?接口应该是客户(即高层模块)来定义,而底层则去实现这些接口,这样,就象是客户提出了它需要的服务,而底层则去实现这些服务,这样当底层实现逻辑发生改变化 时,高层模块将不受响。但有些时候我们不是这样的,我们在定义接口时可能是由底层去定义并公开接口的,这样做会有问题,因为当底层的接口改变时,高层同样 会受到牵连。这就是“接口所有权”的倒置,即由客户定义接口,而不是由“底层”定义接口
五、DIP的关键
DIP是区别于过程化设计与面向对象设计的重要特性。DIP的关键其实在于找到系统中“变”与“不变”的部分,并利用接口将其隔离,这不是一件容易 的事件。因为在系统设计的初期,我们还难预料到系统中那个部分将来是经常会发生变化的部分,只有当事情发生了,我们才有可能知道。这时,我们应该应用 DIP来对系统做出个性,从使你的系统具有应对变化的弹性。
六、遵循DIP会带来的好处
首先,如果你的系统在设计时遵循了DIP原则,那么你的系统在重用时将会变化的容易。再者,由于遵循了DIP,你的系统在应对需求的变化时就有了一定的弹性(更多需求的变化都表现在底层),同时,由于这种弹性,你的系统将更容易维护。
ISP--Interface Segregation Principle 接口隔离原则
接口隔离原则讲的是,使用多个专门的接口比使用单一的总接口要好。一个类对另外一个类的依赖性应当是建立在最小的接口上的。一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。
从一个客户角度讲:一个类对另外一个类的依赖应当是建立在最小接口上的。不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。这个说得很明白了,再通俗点说,不要强迫客户使用它们不用的方法,如果强迫用户使用它们不使用的方法,那么这些客户就会面临由于这些不使用的方法的改变所带来的改变。
CARP--Composite/Aggregate Reuse Principle合成/聚合复用原则
与里氏代换原则关系较为紧密,里氏代换原则告诉我们什么情况下使用extends,在不满足里氏代换原则时,还想达到重用的目的,就引出合成/聚合复用原则。从复用角度来说:“合成/聚合复用”比“继承”复用灵活。前者是动态复用(因而具有可插入性)、后者是静态复用(编译时就固定了复用关系),而且后者的复用有“不支持多重继承”的限制。
CARP就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新对象通过向这些对象的委派达到复用已有功能的目的。简而言之,要尽量使用合成/聚合,尽量不要使用继承。
LoD--Law of Demeter迪米特法则
LKP--Least Knowledge Principle最少知识原则
迪米特法则可以简单说成:talk only to your immediate friends。 对于面向OOD来说,又被解释为下面几种方式:
一个软件实体应当尽可能少的与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。
迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。
迪米特法则不希望类直接建立直接的接触。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。
分享到:
相关推荐
"OOD设计基本原则整理" OOD 设计基本原则之一:开-闭原则 开-闭原则是 OOD 设计的核心原则之一,该原则强调一个软件实体应当对扩展开放,对修改关闭。也就是说,在设计一个软件实体的时候,应当使这个软件实体可以...
OOD 设计基本原则包括 OCP 原则、里氏替换原则、依赖倒置原则、接口隔离原则、聚合与继承原则、单一职责原则、Separation of concerns Principle 和 Pareto Principle 等。 OCP 原则(Open-Closed Principle)是 ...
软件设计的七大原则(OOD) software设计的七大原则是指在软件设计中遵守的一些基本原则,以提高软件的可复用性、灵活性、可扩展性和可维护性。其中包括SRP(单一职责原则)、OCP(开闭原则)、LSP(里氏替换原则)...
面向对象设计(OOD)是面向对象编程(OOP)的进一步发展,OOP提供了封装、继承和多态等基本原则,而OOD则侧重于如何高效、合理地组织这些原则,以创建模块化、可复用和灵活的软件架构。OOD的目标是确保软件能够适应...
OOD 面向对象设计原则与实践 面向对象设计(OOD)是一种软件设计方法,旨在提高软件系统的灵活性、可维护性和可扩展性。OOD 的核心是面向对象设计原则(OOD principles),其中包括单一职责原则(SRP)、开闭原则...
OOD的核心原则包括封装、继承和多态。封装允许我们隐藏实现细节,提供简洁的接口;继承使我们能够创建类之间的层次结构,实现代码复用;多态则让不同类型的对象可以响应相同的消息,增强灵活性。 在OOD中,设计模式...
1. **SOLID原则**:SOLID是五个面向对象设计原则的首字母缩写,包括单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则指导我们编写可维护、可扩展的代码。 2. **设计模式**:设计模式是...
**OOD原则:面向对象设计(Object-Oriented Design)原则** 面向对象设计是软件开发中的一种重要方法,它强调将现实世界中的实体转化为程序中的类和对象,通过封装、继承和多态等特性来实现软件的模块化和可扩展性...
全书共11章,总结出了60多条面向对象设计(OOD)的指导原则。这些经验原则涵盖了从类到对象(主要强调它们之间的关系,包括关联、使用、包含、单继承、多继承)到面向对象物理设计的重要主题。本书将帮助你理解经验...
本知识点总结了图书管理系统的OOD设计准备知识,涵盖了软件设计、模块化设计、软件设计阶段、软件设计目标、软件设计概述、软件结构设计过程、软件设计质量原则、概要设计说明书模板和详细设计说明书模板等方面的...
在Java编程中,OOD是核心的设计原则,通过类、对象、继承、多态、封装等特性来构建可维护、可扩展的系统。 **设计模式** 设计模式是解决常见软件设计问题的模板,它们是经过时间考验、广泛认可的最佳实践。在Java...
7. **原则与指导方针**:OOD遵循一些基本原则,如 SOLID 原则,包括单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)和依赖倒置原则(DIP)。这些原则有助于创建易于理解和维护的...
《OOD启思录》是一本深入探讨面向对象设计(Object-Oriented Design,简称OOD)的经典教材。在软件开发领域,面向对象设计是...通过阅读和实践,你可以更好地理解和应用面向对象设计原则,从而提高软件项目的成功率。
2018年最新OOD面向对象设计专题班的资料,显然聚焦于教授这一核心技能,帮助学员深入理解和应用面向对象设计原则。 面向对象设计的基础是封装、继承和多态三大特性。封装使得数据和操作数据的方法紧密结合,保护了...
设计原则和设计模式是OOD的核心概念,它们为开发者提供了指导思想和最佳实践,以创建可维护、可扩展和易于理解的代码。在Swift中,遵循这些原则和模式可以帮助我们编写出更加灵活和高效的软件。 面向对象设计的原则...
### 面向对象设计原则详解 面向对象设计(Object-Oriented Design,简称OOD)是一种软件设计方法,它强调将复杂系统分解为简单的、相互协作的对象。在面向对象编程中,遵循一定的设计原则是非常重要的,这些原则有...
在进行OOD时,遵循一系列设计原则至关重要: - 模块化:将复杂系统分解为独立的模块。 - 抽象:隐藏实现细节,只暴露必要的接口。 - 信息隐藏:确保对象内部信息不被外部访问。 - 耦合:衡量模块之间的相互依赖程度...
面向对象设计原则是软件开发中的核心指导思想,它们旨在提高代码的可维护性、可扩展性和可重用性。在面向对象设计(OOD)中,遵循这些原则可以帮助我们构建更加稳定、灵活的系统。以下是对这些原则的详细解释: 1. ...