dw做網(wǎng)站怎么用到j(luò)ava免費(fèi)發(fā)帖推廣網(wǎng)站
面向?qū)ο笤O(shè)計(jì)原則
- 面向?qū)ο笤O(shè)計(jì)原則簡介
- 單一職責(zé)原則
- 單一職責(zé)原則定義
- 單一職責(zé)原則分析
- 單一職責(zé)原則實(shí)例
- 開閉原則
- 開閉原則定義
- 開閉原則分析
- 開閉原則實(shí)例
- 里氏代換原則
- 里氏代換原則定義
- 里氏代換原則分析
- 依賴倒轉(zhuǎn)原則
- 依賴倒轉(zhuǎn)原則定義
- 依賴倒轉(zhuǎn)原則分析
- 依賴倒轉(zhuǎn)原則實(shí)例
- 接口隔離原則
- 接口隔離原則定義
- 接口隔離原則分析
- 接口隔離原則實(shí)例
- 合成復(fù)用原則
- 合成復(fù)用原則定義
- 合成復(fù)用原則分析
- 合成復(fù)用原則實(shí)例
- 迪米特法則
- 迪米特法則定義
- 迪米特法則分析
- 狹義的迪米特法則:
- 廣義的迪米特法則:
- 迪米特法則實(shí)例
- 小結(jié)
面向?qū)ο笤O(shè)計(jì)原則簡介
常用的面向?qū)ο笤O(shè)計(jì)原則包括7個(gè),這些原則并不是孤立存在的,它們相互依賴,相互補(bǔ)充。
單一職責(zé)原則
單一職責(zé)原則定義
單一職責(zé)原則(Single Responsibility Principle, SRP)定義如下:
一個(gè)對(duì)象應(yīng)該只包含單一的職責(zé),并且該職責(zé)被完整地封裝在一個(gè)類中。 其英文定義為: Every object should have a
single responsibility, and that responsibility should be entirely
encapsulated by the class. 另一種定義方式如下: 就一個(gè)類而言,應(yīng)該僅有一個(gè)引起它變化的原因。 其英文定義為:
There should never be more than one reason for a class to change.
單一職責(zé)原則分析
一個(gè)類(或者大到模塊,小到方法)承擔(dān)的職責(zé)越多,它被復(fù)用的可能性越小,而且如果一個(gè)類承擔(dān)的職責(zé)過多,就相當(dāng)于將這些職責(zé)耦合在一起,當(dāng)其中一個(gè)職責(zé)變化時(shí),可能會(huì)影響其他職責(zé)的運(yùn)作。
類的職責(zé)主要包括兩個(gè)方面:數(shù)據(jù)職責(zé)和行為職責(zé),數(shù)據(jù)職責(zé)通過其屬性來體現(xiàn),而行為職責(zé)通過其方法來體現(xiàn)。
單一職責(zé)原則是實(shí)現(xiàn)高內(nèi)聚、低耦合的指導(dǎo)方針,在很多代碼重構(gòu)手法中都能找到它的存在,它是最簡單但又最難運(yùn)用的原則,需要設(shè)計(jì)人員發(fā)現(xiàn)類的不同職責(zé)并將其分離,而發(fā)現(xiàn)類的多重職責(zé)需要設(shè)計(jì)人員具有較強(qiáng)的分析設(shè)計(jì)能力和相關(guān)重構(gòu)經(jīng)驗(yàn)。
單一職責(zé)原則實(shí)例
實(shí)例說明
某基于Java的C/S系統(tǒng)的“登錄功能”通過如下登錄類(Login)實(shí)現(xiàn):
現(xiàn)使用單一職責(zé)原則對(duì)其進(jìn)行重構(gòu)。
開閉原則
開閉原則定義
開閉原則(Open-Closed Principle, OCP)定義如下:
一個(gè)軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。也就是說在設(shè)計(jì)一個(gè)模塊的時(shí)候,應(yīng)當(dāng)使這個(gè)模塊可以在不被修改的前提下被擴(kuò)展,即實(shí)現(xiàn)在不修改源代碼的情況下改變這個(gè)模塊的行為。
其英文定義為: Software entities should be open for extension, but closed for
modification.
開閉原則分析
抽象化是開閉原則的關(guān)鍵。
開閉原則還可以通過一個(gè)更加具體的“對(duì)可變性封裝原則”來描述,對(duì)可變性封裝原則(Principle of Encapsulation of Variation, EVP)要求找到系統(tǒng)的可變因素并將其封裝起來。
開閉原則實(shí)例
實(shí)例說明
某圖形界面系統(tǒng)提供了各種不同形狀的按鈕,客戶端代碼可針對(duì)這些按鈕進(jìn)行編程,用戶可能會(huì)改變需求要求使用不同的按鈕,原始設(shè)計(jì)方案如圖所示:
現(xiàn)對(duì)該系統(tǒng)進(jìn)行重構(gòu),使之滿足開閉原則的要求。
里氏代換原則
里氏代換原則定義
里氏代換原則(Liskov Substitution Principle, LSP)有兩種定義方式,第一種定義方式相對(duì)嚴(yán)格,其定義如下:
如果對(duì)每一個(gè)類型為S的對(duì)象o1,都有類型為T的對(duì)象o2,使得以T定義的所有程序P在所有的對(duì)象o1都代換成o2時(shí),程序P的行為沒有變化,那么類型S是類型T的子類型。
其英文定義為:
If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.
第二種更容易理解的定義方式如下:
所有引用基類(父類)的地方必須能透明地使用其子類的對(duì)象。
其英文定義為:
Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
里氏代換原則分析
里氏代換原則可以通俗表述為:在軟件中如果能夠使用基類對(duì)象,那么一定能夠使用其子類對(duì)象。把基類都替換成它的子類,程序?qū)⒉粫?huì)產(chǎn)生任何錯(cuò)誤和異常,反過來則不成立,如果一個(gè)軟件實(shí)體使用的是一個(gè)子類的話,那么它不一定能夠使用基類。
里氏代換原則是實(shí)現(xiàn)開閉原則的重要方式之一,由于使用基類對(duì)象的地方都可以使用子類對(duì)象,因此在程序中盡量使用基類類型來對(duì)對(duì)象進(jìn)行定義,而在運(yùn)行時(shí)再確定其子類類型,用子類對(duì)象來替換父類對(duì)象。
依賴倒轉(zhuǎn)原則
依賴倒轉(zhuǎn)原則定義
依賴倒轉(zhuǎn)原則(Dependence Inversion Principle, DIP)的定義如下:
高層模塊不應(yīng)該依賴低層模塊,它們都應(yīng)該依賴抽象。抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象。
其英文定義為:
High level modules should not depend upon low level modules, both should depend upon abstractions. Abstractions should not depend upon details, details should depend upon abstractions.
另一種表述為:
要針對(duì)接口編程,不要針對(duì)實(shí)現(xiàn)編程。
其英文定義為:
Program to an interface, not an implementation.
依賴倒轉(zhuǎn)原則分析
類之間的耦合
零耦合關(guān)系
具體耦合關(guān)系
抽象耦合關(guān)系
依賴倒轉(zhuǎn)原則要求客戶端依賴于抽象耦合,以抽象方式耦合是依賴倒轉(zhuǎn)原則的關(guān)鍵。
依賴倒轉(zhuǎn)原則實(shí)例
實(shí)例說明
某系統(tǒng)提供一個(gè)數(shù)據(jù)轉(zhuǎn)換模塊,可以將來自不同數(shù)據(jù)源的數(shù)據(jù)轉(zhuǎn)換成多種格式,如可以轉(zhuǎn)換來自數(shù)據(jù)庫的數(shù)據(jù)(DatabaseSource)、也可以轉(zhuǎn)換來自文本文件的數(shù)據(jù)(TextSource),轉(zhuǎn)換后的格式可以是XML文件(XMLTransformer)、也可以是XLS文件(XLSTransformer)等。
實(shí)例說明
由于需求的變化,該系統(tǒng)可能需要增加新的數(shù)據(jù)源或者新的文件格式,每增加一個(gè)新的類型的數(shù)據(jù)源或者新的類型的文件格式,客戶類MainClass都需要修改源代碼,以便使用新的類,但違背了開閉原則?,F(xiàn)使用依賴倒轉(zhuǎn)原則對(duì)其進(jìn)行重構(gòu)。
接口隔離原則
接口隔離原則定義
接口隔離原則(Interface Segregation Principle, ISP)的定義如下:
客戶端不應(yīng)該依賴那些它不需要的接口。
其英文定義為:
Clients should not be forced to depend upon interfaces that they do not use.
注意,在該定義中的接口指的是所定義的方法。
另一種定義方法如下:
一旦一個(gè)接口太大,則需要將它分割成一些更細(xì)小的接口,使用該接口的客戶端僅需知道與之相關(guān)的方法即可。
其英文定義為:
Once an interface has gotten too ‘fat’ it needs to be split into smaller and more specific interfaces so that any clients of the interface will only know about the methods that pertain to them.
接口隔離原則分析
接口隔離原則是指使用多個(gè)專門的接口,而不使用單一的總接口。每一個(gè)接口應(yīng)該承擔(dān)一種相對(duì)獨(dú)立的角色,不多不少,不干不該干的事,該干的事都要干。
(1) 一個(gè)接口就只代表一個(gè)角色,每個(gè)角色都有它特定的一個(gè)接口,此時(shí)這個(gè)原則可以叫做“角色隔離原則”。
(2) 接口僅僅提供客戶端需要的行為,即所需的方法,客戶端不需要的行為則隱藏起來,應(yīng)當(dāng)為客戶端提供盡可能小的單獨(dú)的接口,而不要提供大的總接口。
使用接口隔離原則拆分接口時(shí),首先必須滿足單一職責(zé)原則,將一組相關(guān)的操作定義在一個(gè)接口中,且在滿足高內(nèi)聚的前提下,接口中的方法越少越好。
可以在進(jìn)行系統(tǒng)設(shè)計(jì)時(shí)采用定制服務(wù)的方式,即為不同的客戶端提供寬窄不同的接口,只提供用戶需要的行為,而隱藏用戶不需要的行為。
接口隔離原則實(shí)例
實(shí)例說明
下圖展示了一個(gè)擁有多個(gè)客戶類的系統(tǒng),在系統(tǒng)中定義了一個(gè)巨大的接口(胖接口)AbstractService來服務(wù)所有的客戶類??梢允褂媒涌诟綦x原則對(duì)其進(jìn)行重構(gòu)。
重構(gòu)后
合成復(fù)用原則
合成復(fù)用原則定義
合成復(fù)用原則(Composite Reuse Principle, CRP)又稱為組合/聚合復(fù)用原則(Composition/ Aggregate Reuse Principle, CARP),其定義如下:
盡量使用對(duì)象組合,而不是繼承來達(dá)到復(fù)用的目的。
其英文定義為:
Favor composition of objects over inheritance as a reuse mechanism.
合成復(fù)用原則分析
合成復(fù)用原則就是指在一個(gè)新的對(duì)象里通過關(guān)聯(lián)關(guān)系(包括組合關(guān)系和聚合關(guān)系)來使用一些已有的對(duì)象,使之成為新對(duì)象的一部分;新對(duì)象通過委派調(diào)用已有對(duì)象的方法達(dá)到復(fù)用其已有功能的目的。簡言之:要盡量使用組合/聚合關(guān)系,少用繼承。
組合/聚合可以使系統(tǒng)更加靈活,類與類之間的耦合度降低,一個(gè)類的變化對(duì)其他類造成的影響相對(duì)較少,因此一般首選使用組合/聚合來實(shí)現(xiàn)復(fù)用;其次才考慮繼承,在使用繼承時(shí),需要嚴(yán)格遵循里氏代換原則,有效使用繼承會(huì)有助于對(duì)問題的理解,降低復(fù)雜度,而濫用繼承反而會(huì)增加系統(tǒng)構(gòu)建和維護(hù)的難度以及系統(tǒng)的復(fù)雜度,因此需要慎重使用繼承復(fù)用。
合成復(fù)用原則實(shí)例
實(shí)例說明
某教學(xué)管理系統(tǒng)部分?jǐn)?shù)據(jù)庫訪問類設(shè)計(jì)如圖所示:
實(shí)例說明
如果需要更換數(shù)據(jù)庫連接方式,如原來采用JDBC連接數(shù)據(jù)庫,現(xiàn)在采用數(shù)據(jù)庫連接池連接,則需要修改DBUtil類源代碼。如果StudentDAO采用JDBC連接,但是TeacherDAO采用連接池連接,則需要增加一個(gè)新的DBUtil類,并修改StudentDAO或TeacherDAO的源代碼,使之繼承新的數(shù)據(jù)庫連接類,這將違背開閉原則,系統(tǒng)擴(kuò)展性較差。
現(xiàn)使用合成復(fù)用原則對(duì)其進(jìn)行重構(gòu)。
迪米特法則
迪米特法則定義
迪米特法則(Law of Demeter, LoD)又稱為最少知識(shí)原則(Least Knowledge Principle, LKP),它有多種定義方法,其中幾種典型定義如下:
(1) 不要和“陌生人”說話。英文定義為:Don’t talk to strangers.
(2) 只與你的直接朋友通信。英文定義為:Talk only to your immediate friends.
(3) 每一個(gè)軟件單位對(duì)其他的單位都只有最少的知識(shí),而且局限于那些與本單位密切相關(guān)的軟件單位。英文定義為:Each unit should have only limited knowledge about other units: only units “closely” related to the current unit.
迪米特法則分析
迪米特法則來自于1987年秋美國東北大學(xué)(Northeastern University)一個(gè)名為“Demeter”的研究項(xiàng)目。
簡單地說,迪米特法則就是指一個(gè)軟件實(shí)體應(yīng)當(dāng)盡可能少的與其他實(shí)體發(fā)生相互作用。這樣,當(dāng)一個(gè)模塊修改時(shí),就會(huì)盡量少的影響其他的模塊,擴(kuò)展會(huì)相對(duì)容易,這是對(duì)軟件實(shí)體之間通信的限制,它要求限制軟件實(shí)體之間通信的寬度和深度。
在迪米特法則中,對(duì)于一個(gè)對(duì)象,其朋友包括以下幾類:
(1) 當(dāng)前對(duì)象本身(this);
(2) 以參數(shù)形式傳入到當(dāng)前對(duì)象方法中的對(duì)象;
(3) 當(dāng)前對(duì)象的成員對(duì)象;
(4) 如果當(dāng)前對(duì)象的成員對(duì)象是一個(gè)集合,那么集合中的元素也都是朋友;
(5) 當(dāng)前對(duì)象所創(chuàng)建的對(duì)象。
任何一個(gè)對(duì)象,如果滿足上面的條件之一,就是當(dāng)前對(duì)象的“朋友”,否則就是“陌生人”。
迪米特法則可分為狹義法則和廣義法則。在狹義的迪米特法則中,如果兩個(gè)類之間不必彼此直接通信,那么這兩個(gè)類就不應(yīng)當(dāng)發(fā)生直接的相互作用,如果其中的一個(gè)類需要調(diào)用另一個(gè)類的某一個(gè)方法的話,可以通過第三者轉(zhuǎn)發(fā)這個(gè)調(diào)用。
狹義的迪米特法則:
可以降低類之間的耦合,但是會(huì)在系統(tǒng)中增加大量的小方法并散落在系統(tǒng)的各個(gè)角落,它可以使一個(gè)系統(tǒng)的局部設(shè)計(jì)簡化,因?yàn)槊恳粋€(gè)局部都不會(huì)和遠(yuǎn)距離的對(duì)象有直接的關(guān)聯(lián),但是也會(huì)造成系統(tǒng)的不同模塊之間的通信效率降低,使得系統(tǒng)的不同模塊之間不容易協(xié)調(diào)。
廣義的迪米特法則:
指對(duì)對(duì)象之間的信息流量、流向以及信息的影響的控制,主要是對(duì)信息隱藏的控制。信息的隱藏可以使各個(gè)子系統(tǒng)之間脫耦,從而允許它們獨(dú)立地被開發(fā)、優(yōu)化、使用和修改,同時(shí)可以促進(jìn)軟件的復(fù)用,由于每一個(gè)模塊都不依賴于其他模塊而存在,因此每一個(gè)模塊都可以獨(dú)立地在其他的地方使用。一個(gè)系統(tǒng)的規(guī)模越大,信息的隱藏就越重要,而信息隱藏的重要性也就越明顯。
迪米特法則的主要用途在于控制信息的過載:
在類的劃分上,應(yīng)當(dāng)盡量創(chuàng)建松耦合的類,類之間的耦合度越低,就越有利于復(fù)用,一個(gè)處在松耦合中的類一旦被修改,不會(huì)對(duì)關(guān)聯(lián)的類造成太大波及;
在類的結(jié)構(gòu)設(shè)計(jì)上,每一個(gè)類都應(yīng)當(dāng)盡量降低其成員變量和成員函數(shù)的訪問權(quán)限;
在類的設(shè)計(jì)上,只要有可能,一個(gè)類型應(yīng)當(dāng)設(shè)計(jì)成不變類;
在對(duì)其他類的引用上,一個(gè)對(duì)象對(duì)其他對(duì)象的引用應(yīng)當(dāng)降到最低。
迪米特法則實(shí)例
實(shí)例說明
某系統(tǒng)界面類(如Form1、Form2等類)與數(shù)據(jù)訪問類(如DAO1、DAO2等類)之間的調(diào)用關(guān)系較為復(fù)雜,如圖所示:
重構(gòu)后
小結(jié)
對(duì)于面向?qū)ο蟮能浖到y(tǒng)設(shè)計(jì)來說,在支持可維護(hù)性的同時(shí),需要提高系統(tǒng)的可復(fù)用性。
軟件的復(fù)用可以提高軟件的開發(fā)效率,提高軟件質(zhì)量,節(jié)約開發(fā)成本,恰當(dāng)?shù)膹?fù)用還可以改善系統(tǒng)的可維護(hù)性。
單一職責(zé)原則要求在軟件系統(tǒng)中,一個(gè)類只負(fù)責(zé)一個(gè)功能領(lǐng)域中的相應(yīng)職責(zé)。
開閉原則要求一個(gè)軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉,即在不修改源代碼的基礎(chǔ)上擴(kuò)展一個(gè)系統(tǒng)的行為。
里氏代換原則可以通俗表述為在軟件中如果能夠使用基類對(duì)象,那么一定能夠使用其子類對(duì)象。
依賴倒轉(zhuǎn)原則要求抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象;要針對(duì)接口編程,不要針對(duì)實(shí)現(xiàn)編程。
接口隔離原則要求客戶端不應(yīng)該依賴那些它不需要的接口,即將一些大的接口細(xì)化成一些小的接口供客戶端使用。
合成復(fù)用原則要求復(fù)用時(shí)盡量使用對(duì)象組合,而不使用繼承。
迪米特法則要求一個(gè)軟件實(shí)體應(yīng)當(dāng)盡可能少的與其他實(shí)體發(fā)生相互作用。