轉(zhuǎn)帖|行業(yè)資訊|編輯:蔣永|2017-02-15 11:13:23.000|閱讀 151 次
概述:本文宗旨是向沒有接觸過或正處于學(xué)習(xí)階段的Java程序員介紹面向?qū)ο笤O(shè)計原則,希望對大家有所幫助~
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
面向?qū)ο笤O(shè)計原則是OOPS編程的核心, 但大多數(shù)Java程序員熱心于像Singleton (單例) 、 Decorator(裝飾器)、Observer(觀察者) 等設(shè)計模式,而沒有把足夠多的注意力放在學(xué)習(xí)面向?qū)ο蟮姆治龊驮O(shè)計上面。學(xué)習(xí)面向?qū)ο缶幊滔?ldquo;抽象”、“封裝”、“多態(tài)”、“繼承” 等基礎(chǔ)知識是重要的,但同時為了創(chuàng)建簡潔、模塊化的設(shè)計,了解這些設(shè)計原則也同等重要。經(jīng)常看到不同經(jīng)驗水平的java程序員,他們有的不知道這些OOPS 和SOLID設(shè)計原則,有的只是不知道一個特定的設(shè)計原則會帶來怎樣的益處,甚至不知道在編碼中如何使用這些設(shè)計原則。
設(shè)計原則底線是永遠(yuǎn)追求高內(nèi)聚、低耦合的編碼或設(shè)計。 Apache 和 Sun的開源代碼是學(xué)習(xí)Java和OOPS設(shè)計原則的良好范例。它們向我們展示了,設(shè)計原則在Java編程中是如何使用的。JavaJDK 使用了一些設(shè)計原則:BorderFactory類中的工廠模式、Runtime類中的單例模式、java.io 類中的裝飾器模式。順便說一句,如果您真的對Java編碼原則感興趣,請閱讀Joshua Bloch 的Effective Java,他編寫過Java API。我個人最喜歡的關(guān)于面向?qū)ο笤O(shè)計模式的是Kathy Sierra的Head First Design Pattern(深入淺出設(shè)計模式),以及其它的關(guān)于深入淺出面向?qū)ο蠓治龊驮O(shè)計。這些書對編寫更好的代碼有很大幫助,充分利用各種面向?qū)ο蠛蚐OLID的設(shè)計模式。
雖然學(xué)習(xí)設(shè)計模式(原則)最好的方法是現(xiàn)實中的例子和理解違反設(shè)計原則帶來的不便,本文的宗旨是向那些沒有接觸過或正處于學(xué)習(xí)階段的Java程序員介紹面向?qū)ο笤O(shè)計原則。
在軟件領(lǐng)域永遠(yuǎn)不變的是“變化”,所以把您認(rèn)為或懷疑將來要被修改的代碼封裝起來。這種面向?qū)ο笤O(shè)計模式的優(yōu)點是:易于測試和維護恰當(dāng)封裝的代碼。如果您在用Java編程,那么請遵守以下原則:變量和方法的訪問權(quán)限默認(rèn)設(shè)置為私有,并且逐步放開它們的訪問權(quán)限,例如從“private”到“protected ”、“not public”。Java中的一些設(shè)計模式使用了封裝,工廠設(shè)計模式就是一個例子,它封裝了創(chuàng)建對象的代碼而且提供了以下靈活性:后續(xù)生成新對象不影響現(xiàn)有的代碼。
類、方法/函數(shù)應(yīng)當(dāng)是對擴展(新功能)開放,對修改閉合。這是另外一個優(yōu)雅的SOLID 設(shè)計原則,以防止有人修改通過測試的代碼。理想情況下假如您添加了新功能,那么您的代碼要經(jīng)過測試,這就是打開/關(guān)閉設(shè)計原則的目標(biāo)。順便說一句,SOLID中的字母“O”指的是打開/關(guān)閉設(shè)計原則。
單一職責(zé)原則是另外一個SOLID設(shè)計原則,SOLID中的字母“S”指的就是它。按照SRP,一個類修改的原因應(yīng)當(dāng)有且只有一個,或者一個類應(yīng)當(dāng)總是實現(xiàn)單一功能。如果您在Java中的一個類實現(xiàn)了多個功能,那么這些功能之間便產(chǎn)生了耦合關(guān)系;如果您修改其中的一個功能,您有可能就打破了這種耦合關(guān)系,那么就要進行另一輪測試以避免產(chǎn)生新的問題。
不要問框架的依賴注入功能將會給你帶來什么益處,依賴注入功能在spring框架里已經(jīng)很好的得到了實現(xiàn),這一設(shè)計原則的優(yōu)雅之處在于:DI框架注入的任何一個類都易于用模擬對象進行測試,并且更易于維護,因為創(chuàng)建對象的代碼在框架里是集中的而且和客戶端代碼是隔離的。有多種方法可以實現(xiàn)依賴注入,例如使用字節(jié)碼工具,其中一些AOP(面向切面編程)框架如切入點表達式或者spring里使用的代理。想對這種SOLID設(shè)計原則了解更多,請看IOC 和 DI設(shè)計模式中的例子。 SOLID中的字母“D”指的就是這種設(shè)計原則。
如果可以的話,要優(yōu)先使用組合而非繼承。你們中的一些人可能為此爭論,但我發(fā)現(xiàn)組合比繼承更有靈活性。組合允許在運行時通過設(shè)置屬性修改一個類的行為,通過使用多態(tài)即以接口的形式實現(xiàn)類之間的組合關(guān)系,并且為修改組合關(guān)系提供了靈活性。甚至 Effective Java也建議優(yōu)先使用組合而非繼承。
根據(jù)里氏替換原則,父類出現(xiàn)的地方可以用子類來替換,例如父類的方法或函數(shù)被子類對象替換應(yīng)該沒有任何問題。LSP和單一職責(zé)原則、接口隔離原則密切相關(guān)。如果一個父類的功能比其子類還要多,那么它可能不支持這一功能,而且也違反了LSP設(shè)計原則。為了遵循 LSP SOLID設(shè)計原則,派生類或子類(相對父類比較)必須增強功能,而非減少。SOLID中的字母“L”指的就是 LSP設(shè)計原則。
接口隔離原則指,如果不需要一個接口的功能,那么就不要實現(xiàn)此接口。這大多在以下情況發(fā)生:一個接口包含多種功能,而實現(xiàn)類只需要其中一種功能。接口設(shè)計是一種棘手的工作,因為一旦發(fā)布了接口,您就不能修改它否則會影響實現(xiàn)該接口的類。在Java中這種設(shè)計原則的另一個好處是:接口有一個特點,任何類使用它之前都要實現(xiàn)該接口所有的方法,所以使用功能單一的接口意味著實現(xiàn)更少的方法。
編程總是以接口(而非實現(xiàn)對象)為中心,這會使代碼的結(jié)構(gòu)靈活,而且任何一個新的接口實現(xiàn)對象都能兼容現(xiàn)有代碼結(jié)構(gòu)。所以在Java中,變量、方法返回值、方法參數(shù)的數(shù)據(jù)類型請使用接口。這是許多Java程序員的建議, Effective Java 以及 head first design pattern 等書也這樣建議。
不要期望一個類完成所有的功能,可以適當(dāng)?shù)匕岩恍┕?能交給代理類實現(xiàn)。代理原則的典范是:Java 中的equals() 和 hashCode() 方法。為了比較兩個對象的內(nèi)容是否相同,我們讓用于比較的類本身完成對比工作而非它們的調(diào)用方。這種設(shè)計原則的好處是:沒有重復(fù)編碼而且很容易修改類的行為。
以上所有面向?qū)ο蟮脑O(shè)計原則可以幫助您寫出靈活、優(yōu)雅的代碼:具有高內(nèi)聚低耦合的代碼結(jié)構(gòu)。理論只是第一步,更重要的是我們要習(xí)得一種能力去發(fā)現(xiàn)什么時候使用這些設(shè)計原則。去發(fā)現(xiàn)我們是否違反了什么設(shè)計原則和影響了代碼的靈活性,但是世界上沒有什么是完美的,我們解決問題時不能總?cè)ナ褂迷O(shè)計模式和設(shè)計原則,它們大多用于有較長維護周期的大型企業(yè)項目。
本文轉(zhuǎn)自()
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn