出處:http://www.codeproject.com/Articles/60845/The-S-O-L-I-D-Object-Oriented-Programming-OOP-Prin
Introduction
The S.O.L.I.D. Principles of Class Design
The Single Responsibility Principle
The Open Closed Principle
The Liskov Substitution Principle
The Interface Segregation Principle
The Dependency Inversion Principle
- Create an abstract class (named DataWriter, perhaps) that can be inherited from for XML (XMLDataWriter) or DB (DbDataWriter) Saving, and then
- Create a class (named EmployeeWriter) that would expose an Output(DataWriter saveMethod) that accepts a dependency as an argument. See how the Output method is dependent upon the abstractions just as the output types are? The dependencies have been inverted. Now we can create new types of ways for Employee data to be written, perhaps via HTTP/HTTPS by creating abstractions, and without modifying any of our previous code! No rigidity–the desired outcome.
Sources
License
=======================================================================
OO的五大原則
出處:http://blog.csdn.net/httphttpcn/article/details/5783903
在学习和使用OO设计的时候,我们应该明白:OO的出现使得软件工程师们能够用更接近真实世界的方法描述软件系统。然而,软件毕竟是建立在抽象层次上的东西,再怎么接近真实,也不能替代真实或被真实替代。
OO设计的五大原则之间并不是相互孤立的。彼此间存在着一定关联,一个可以是另一个原则的加强或是基础。违反其中的某一个,可能同时违反了其余的原则。因此应该把这些原则融会贯通,牢记在心!
OO的五大原则是指SRP、OCP、LSP、DIP、ISP。
1. SRP(Single Responsibility Principle 单一职责原则)
单一职责很容易理解,也很容易实现。所谓单一职责,就是一个设计元素只做一件事。什么是“只做一件事”?简单说就是少管闲事。现实中就是如此,如果要你专心做一件事情,任何人都有信心可以做得很出色。
OCP作为OO的高层原则,主张使用“抽象(Abstraction)”和“多态(Polymorphism)”将设计中的静态结构改为动态结构,维持设计的封闭性。
2. OCP :开闭原则,很简单,一句话:“Closed for Modification; Open for Extension”——“对变更关闭;对扩展开放”。开闭原则其实没什么好讲的,我将其归结为一个高层次的设计总则。OCP的动机很简单:软件是变化的。不论是优质的设计还是低劣的设计都无法回避这一问题。OCP说明了软件设计应该尽可能地使架构稳定而又容易满足不同的需求。 为什么要OCP?答案也很简单——重用。
3.LSP——里氏替换原则
OCP作为OO的高层原则,主张使用“抽象(Abstraction)”和“多态(Polymorphism)”将设计中的静态结构改为动态结构,维持设计的封闭性“抽象”是语言提供的功能。“多态”由继承语义实现。 如此,问题产生了:“我们如何去度量继承关系的质量?”
Liskov于1987年提出了一个关于继承的原则“Inheritance should ensure that any property proved about supertype objects also holds for subtype objects.”——“继承必须确保超类所拥有的性质在子类中仍然成立。”也就是说,当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-A关系。
该原则称为Liskov Substitution Principle——里氏替换原则。
我们来研究一下LSP的实质。学习OO的时候,我们知道,一个对象是一组状态和一系列行为的组合体。状态是对象的内在特性,行为是对象的外在特性。LSP所表述的就是在同一个继承体系中的对象应该有共同的行为特征。
这一点上,表明了OO的继承与日常生活中的继承的本质区别。举一个例子:生物学的分类体系中把企鹅归属为鸟类。我们模仿这个体系,设计出这样的类和关系。
类“鸟”中有个方法fly,企鹅自然也继承了这个方法,可是企鹅不能飞阿,于是,我们在企鹅的类中覆盖了fly方法,告诉方法的调用者:企鹅是不会飞的。这完全符合常理。但是,这违反了LSP,企鹅是鸟的子类,可是企鹅却不能飞!需要注意的是,此处的“鸟”已经不再是生物学中的鸟了,它是软件中的一个类、一个抽象。
有人会说,企鹅不能飞很正常啊,而且这样编写代码也能正常编译,只要在使用这个类的客户代码中加一句判断就行了。但是,这就是问题所在!首先,客户代码和“企鹅”的代码很有可能不是同时设计的,在当今软件外包一层又一层的开发模式下,你甚至根本不知道两个模块的原产地是哪里,也就谈不上去修改客户代码了。客户程序很可能是遗留系统的一部分,很可能已经不再维护,如果因为设计出这么一个“企鹅”而导致必须修改客户代码,谁应该承担这部分责任呢?(大概是上帝吧,谁叫他让“企鹅”不能飞的。^_^)“修改客户代码”直接违反了OCP,这就是OCP的重要性。违反LSP将使既有的设计不能封闭!
修正后的设计如下:
LSP并没有提供解决这个问题的方案,而只是提出了这么一个问题。 于是,工程师们开始关注如何确保对象的行为。1988年,B. Meyer提出了Design by Contract(契约式设计)理论。DbC从形式化方法中借鉴了一套确保对象行为和自身状态的方法,其基本概念很简单:
每个方法调用之前,该方法应该校验传入参数的正确性,只有正确才能执行该方法,否则认为调用方违反契约,不予执行。这称为前置条件(Pre-condition)。
一旦通过前置条件的校验,方法必须执行,并且必须确保执行结果符合契约,这称之为后置条件(Post-condition)。
对象本身有一套对自身状态进行校验的检查条件,以确保该对象的本质不发生改变,这称之为不变式(Invariant)。
以上是单个对象的约束条件。为了满足LSP,当存在继承关系时,子类中方法的前置条件必须与超类中被覆盖的方法的前置条件相同或者更宽松;而子类中方法的后置条件必须与超类中被覆盖的方法的后置条件相同或者更为严格。
4.DIP 依赖倒置原则
依赖倒置(Dependence Inversion Principle)原则讲的是:要依赖于抽象,不要依赖于具体。
简单的说,依赖倒置原则要求客户端依赖于抽象耦合。原则表述:
抽象不应当依赖于细节;细节应当依赖于抽象;
要针对接口编程,不针对实现编程。
5.ISP 接口隔离原则
使用多个专门的接口比使用单一的总接口要好。广义的接口:一个接口相当于剧本中的一种角色,而此角色在一个舞台上由哪一个演员来演则相当于接口的实现。因此一个接口应当简单的代表一个角色,而不是一个角色。,如果系统设计多哥角色的话,则应当每一个角色都由一个特定的接口代表。狭义的接口(Interface):接口隔离原则讲的就是同一个角色提供宽、窄不同的接口,以对付不同的客户端。
===============================================================================
白話- OO設計原則 (SOLID原則) – 附生活實例
出處:http://rockssdlog.blogspot.tw/2012/03/oo-solid.html
以下的5個原則,也稱為SOLID原則,是用來檢視當系統需求改變時,你是否能快速、安心的面對。是否應該引用Design Pattern,也可用目前是否符合這些原則來做檢視。
這些原則間並非完全互斥,即當你發現違反了某個原則時,通常也會違反其他原則。而其中最重要的便是OCP原則。
1. SRP:Single Responsibility Principle(單一職責)
定義:一個class應該只有一個需要改變的原因。
There should never be more than one reason for a class to change.
白話:一個class只作一件事。
問題:
1)到底切多細,很難一開始就知道。
2)切太細造成複雜度過高。
2. OCP: Open Closed Principle(開放封閉)
定義:軟體設計,應該對擴充開放,對修改封閉。
Software entities like classes, modules and functions should be open for extension but closed for modifications.
白話:軟體要很容易擴充功能,且擴充時原有的code都不需修改。
重要性:OCP是OOD諸多主張的核心。
生活實例:
某情聖:『我永遠在電話中叫女朋友"寶貝",這樣怎麼換人或劈腿都不會穿幫』
3. LSP : Liskov Substitution Principle(Liskov替換)
定義:子類必須能夠替換其父類別。
Inheritance should ensure that any property proved about supertype objects also holds for subtype objects.
白話:設計父類別時,只把所有的子類都有的東西放進來。
生活實例:
女兒問你『把拔,什麼是鳥類?』
你很得意的說『很簡單啊,就是會飛的動物嘛!』 (把『會飛』加到『鳥類』這個概念中)
接著打開鳥類大百科開始解說:
『就像這個老鷹就是會飛的動物』
『這個烏鴉也是會飛的動物 』
『還有………這個… 企鵝 ……?』@ @|||
PS.『不會飛的鳥』請見Wiki…
與OCP關係:LSP也是為了確保子類別擴充時不會違反OCP 。
4. ISP:Interface Segregation Principle(介面隔離)
定義:客戶(Client)只要依賴它們所需的介面
Clients should not be forced to depend upon interfaces that they don’t use.
白話:設計介面也盡量簡單,別把不相關的東西放進來。
生活實例:
業務員:『太太!你看我們最新的遙控器,可以遙控電視、冷氣、撥放器,連洗衣機也可以遙控,讓你一機在手家事一手包辦…』
太太:『那我衣服洗到一半,被轉電視的小朋友按到停止怎麼辦?可以把洗衣機的部分拿掉嗎?』
業務員:『…』
解決方式:
1)委任
2)多重繼承
5. DIP : Dependency Inversion Principle(依賴倒轉)
定義:
1)高階模組不應依賴低階模組,兩者應依賴抽象概念。
High-level modules should not depend on low-level modules. Both should depend on abstractions.
2)抽象概念不應依賴細節,細節應依賴抽象概念。
Abstractions should not depend on details. Details should depend on abstractions.
白話:不要具體的指明物件的關係,而要抽象觀念替代之。
生活實例:
你下班快到家時,接到老婆的電話,才驚覺今天是結婚紀念日。
千萬別在電話中說,『當然,我帶了妳最愛的玫瑰花回家哦!』(具體)
因為很可能稍後發現……附近的花店都關門了…
只要說『當然,親愛的,我帶了禮物回家』(抽象)
這樣一來就能看到路邊賣什麼就買什麼。