真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

開閉原則java代碼舉例,代碼的開閉原則

常見代碼重構(gòu)技巧(非常實用)

1_代碼重構(gòu)漫畫.jpeg

成都創(chuàng)新互聯(lián)公司從2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目網(wǎng)站制作、做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元旌陽做網(wǎng)站,已為上家服務(wù),為旌陽各地企業(yè)和個人服務(wù),聯(lián)系電話:13518219792

項目在不斷演進(jìn)過程中,代碼不停地在堆砌。如果沒有人為代碼的質(zhì)量負(fù)責(zé),代碼總是會往越來越混亂的方向演進(jìn)。當(dāng)混亂到一定程度之后,量變引起質(zhì)變,項目的維護(hù)成本已經(jīng)高過重新開發(fā)一套新代碼的成本,想要再去重構(gòu),已經(jīng)沒有人能做到了。

造成這樣的原因往往有以下幾點:

對于此類問題,業(yè)界已有有很好的解決思路:通過持續(xù)不斷的重構(gòu)將代碼中的“壞味道”清除掉。

重構(gòu)一書的作者M(jìn)artin Fowler對重構(gòu)的定義:

根據(jù)重構(gòu)的規(guī)??梢源笾路譃榇笮椭貥?gòu)和小型重構(gòu):

大型重構(gòu) :對頂層代碼設(shè)計的重構(gòu),包括:系統(tǒng)、模塊、代碼結(jié)構(gòu)、類與類之間的關(guān)系等的重構(gòu),重構(gòu)的手段有:分層、模塊化、解耦、抽象可復(fù)用組件等等。這類重構(gòu)的工具就是我們學(xué)習(xí)過的那些設(shè)計思想、原則和模式。這類重構(gòu)涉及的代碼改動會比較多,影響面會比較大,所以難度也較大,耗時會比較長,引入bug的風(fēng)險也會相對比較大。

小型重構(gòu) :對代碼細(xì)節(jié)的重構(gòu),主要是針對類、函數(shù)、變量等代碼級別的重構(gòu),比如規(guī)范命名和注釋、消除超大類或函數(shù)、提取重復(fù)代碼等等。小型重構(gòu)更多的是使用統(tǒng)一的編碼規(guī)范。這類重構(gòu)要修改的地方比較集中,比較簡單,可操作性較強,耗時會比較短,引入bug的風(fēng)險相對來說也會比較小。什么時候重構(gòu) 新功能開發(fā)、修bug或者代碼review中出現(xiàn)“代碼壞味道”,我們就應(yīng)該及時進(jìn)行重構(gòu)。持續(xù)在日常開發(fā)中進(jìn)行小重構(gòu),能夠降低重構(gòu)和測試的成本。

2_代碼常見問題.png

代碼重復(fù)

方法過長

過大的類

邏輯分散

嚴(yán)重的情結(jié)依戀

數(shù)據(jù)泥團(tuán)/基本類型偏執(zhí)

不合理的繼承體系

過多的條件判斷

過長的參數(shù)列

臨時變量過多

令人迷惑的暫時字段

純數(shù)據(jù)類

不恰當(dāng)?shù)拿?/p>

過多的注釋

3_代碼質(zhì)量如何衡量.jpg

代碼質(zhì)量的評價有很強的主觀性,描述代碼質(zhì)量的詞匯也有很多,比如可讀性、可維護(hù)性、靈活、優(yōu)雅、簡潔。這些詞匯是從不同的維度去評價代碼質(zhì)量的。其中,可維護(hù)性、可讀性、可擴(kuò)展性又是提到最多的、最重要的三個評價標(biāo)準(zhǔn)。

要寫出高質(zhì)量代碼,我們就需要掌握一些更加細(xì)化、更加能落地的編程方法論,這就包含面向?qū)ο笤O(shè)計思想、設(shè)計原則、設(shè)計模式、編碼規(guī)范、重構(gòu)技巧等。

4_SOLID原則.png

一個類只負(fù)責(zé)完成一個職責(zé)或者功能,不要存在多于一種導(dǎo)致類變更的原因。

單一職責(zé)原則通過避免設(shè)計大而全的類,避免將不相關(guān)的功能耦合在一起,來提高類的內(nèi)聚性。同時,類職責(zé)單一,類依賴的和被依賴的其他類也會變少,減少了代碼的耦合性,以此來實現(xiàn)代碼的高內(nèi)聚、松耦合。但是,如果拆分得過細(xì),實際上會適得其反,反倒會降低內(nèi)聚性,也會影響代碼的可維護(hù)性。

添加一個新的功能,應(yīng)該是通過在已有代碼基礎(chǔ)上擴(kuò)展代碼(新增模塊、類、方法、屬性等),而非修改已有代碼(修改模塊、類、方法、屬性等)的方式來完成。

開閉原則并不是說完全杜絕修改,而是以最小的修改代碼的代價來完成新功能的開發(fā)。

很多設(shè)計原則、設(shè)計思想、設(shè)計模式,都是以提高代碼的擴(kuò)展性為最終目的的。特別是 23 種經(jīng)典設(shè)計模式,大部分都是為了解決代碼的擴(kuò)展性問題而總結(jié)出來的,都是以開閉原則為指導(dǎo)原則的。最常用來提高代碼擴(kuò)展性的方法有:多態(tài)、依賴注入、基于接口而非實現(xiàn)編程,以及大部分的設(shè)計模式(比如,裝飾、策略、模板、職責(zé)鏈、狀態(tài))。

子類對象(object of subtype/derived class)能夠替換程序(program)中父類對象(object of base/parent class)出現(xiàn)的任何地方,并且保證原來程序的邏輯行為(behavior)不變及正確性不被破壞。

子類可以擴(kuò)展父類的功能,但不能改變父類原有的功能

調(diào)用方不應(yīng)該依賴它不需要的接口;一個類對另一個類的依賴應(yīng)該建立在最小的接口上。接口隔離原則提供了一種判斷接口的職責(zé)是否單一的標(biāo)準(zhǔn):通過調(diào)用者如何使用接口來間接地判定。如果調(diào)用者只使用部分接口或接口的部分功能,那接口的設(shè)計就不夠職責(zé)單一。

高層模塊不應(yīng)該依賴低層模塊,二者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴抽象。

一個對象應(yīng)該對其他對象保持最少的了解

盡量使用合成/聚合的方式,而不是使用繼承。

單一職責(zé)原則告訴我們實現(xiàn)類要職責(zé)單一;里氏替換原則告訴我們不要破壞繼承體系;依賴倒置原則告訴我們要面向接口編程;接口隔離原則告訴我們在設(shè)計接口的時候要精簡單一;迪米特法則告訴我們要降低耦合。而開閉原則是總綱,告訴我們要對擴(kuò)展開放,對修改關(guān)閉。

image.png

模塊結(jié)構(gòu)說明

代碼開發(fā)要遵守各層的規(guī)范,并注意層級之間的依賴關(guān)系。

多個方法代碼重復(fù)、方法中代碼過長或者方法中的語句不在一個抽象層級。

方法是代碼復(fù)用的最小粒度,方法過長不利于復(fù)用,可讀性低,提煉方法往往是重構(gòu)工作的第一步。

意圖導(dǎo)向編程 :把處理某件事的流程和具體做事的實現(xiàn)方式分開。

將函數(shù)放進(jìn)一個單獨對象中,如此一來局部變量就變成了對象內(nèi)的字段。然后你可以在同一個對象中將這個大型函數(shù)分解為多個小型函數(shù)。

方法參數(shù)比較多時,將參數(shù)封裝為參數(shù)對象

任何有返回值的方法,都不應(yīng)該有副作用

臨時變量僅使用一次或者取值邏輯成本很低的情況下

將復(fù)雜表達(dá)式(或其中一部分)的結(jié)果放進(jìn)一個臨時變量,以此變量名稱來解釋表達(dá)式用途

把復(fù)雜的條件表達(dá)式拆分成多個條件表達(dá)式,減少嵌套。嵌套了好幾層的if - then-else語句,轉(zhuǎn)換為多個if語句

當(dāng)出現(xiàn)大量類型檢查和判斷時,if else(或switch)語句的體積會比較臃腫,這無疑降低了代碼的可讀性。 另外,if else(或switch)本身就是一個“變化點”,當(dāng)需要擴(kuò)展新的類型時,我們不得不追加if else(或switch)語句塊,以及相應(yīng)的邏輯,這無疑降低了程序的可擴(kuò)展性,也違反了面向?qū)ο蟮拈_閉原則。

非正常業(yè)務(wù)狀態(tài)的處理,使用拋出異常的方式代替返回錯誤碼

某一段代碼需要對程序狀態(tài)做出某種假設(shè),以斷言明確表現(xiàn)這種假設(shè)。

當(dāng)使用一個方法返回的對象時,而這個對象可能為空,這個時候需要對這個對象進(jìn)行操作前,需要進(jìn)行判空,否則就會報空指針。當(dāng)這種判斷頻繁的出現(xiàn)在各處代碼之中,就會影響代碼的美觀程度和可讀性,甚至增加Bug的幾率。

空引用的問題在Java中無法避免,但可以通過代碼編程技巧(引入空對象)來改善這一問題。

根據(jù)單一職責(zé)原則,一個類應(yīng)該有明確的責(zé)任邊界。但在實際工作中,類會不斷的擴(kuò)展。當(dāng)給某個類添加一項新責(zé)任時,你會覺得不值得分離出一個單獨的類。于是,隨著責(zé)任不斷增加,這個類包含了大量的數(shù)據(jù)和函數(shù),邏輯復(fù)雜不易理解。

此時你需要考慮將哪些部分分離到一個單獨的類中,可以依據(jù)高內(nèi)聚低耦合的原則。如果某些數(shù)據(jù)和方法總是一起出現(xiàn),或者某些數(shù)據(jù)經(jīng)常同時變化,這就表明它們應(yīng)該放到一個類中。另一種信號是類的子類化方式:如果你發(fā)現(xiàn)子類化只影響類的部分特性,或者類的特性需要以不同方式來子類化,這就意味著你需要分解原來的類。

繼承使實現(xiàn)代碼重用的有力手段,但這并非總是完成這項工作的最佳工具,使用不當(dāng)會導(dǎo)致軟件變得很脆弱。與方法調(diào)用不同的是,繼承打破了封裝性。子類依賴于其父類中特定功能的實現(xiàn)細(xì)節(jié),如果父類的實現(xiàn)隨著發(fā)行版本的不同而變化,子類可能會遭到破壞,即使他的代碼完全沒有改變。

舉例說明,假設(shè)有一個程序使用HashSet,為了調(diào)優(yōu)該程序的性能,需要統(tǒng)計HashSet自從它創(chuàng)建以來添加了多少個元素。為了提供該功能,我們編寫一個HashSet的變體。

通過在新的類中增加一個私有域,它引用現(xiàn)有類的一個實例,這種設(shè)計被稱為組合,因為現(xiàn)有的類變成了新類的一個組件。這樣得到的類將會非常穩(wěn)固,它不依賴現(xiàn)有類的實現(xiàn)細(xì)節(jié)。即使現(xiàn)有的類添加了新的方法,也不會影響新的類。許多設(shè)計模式使用就是這種套路,比如代理模式、裝飾者模式

繼承與組合如何取舍

Java提供了兩種機(jī)制,可以用來定義允許多個實現(xiàn)的類型:接口和抽象類。自從Java8為接口增加缺省方法(default method),這兩種機(jī)制都允許為實例方法提供實現(xiàn)。主要區(qū)別在于,為了實現(xiàn)由抽象類定義的類型,類必須稱為抽象類的一個子類。因為Java只允許單繼承,所以用抽象類作為類型定義受到了限制。

接口相比于抽象類的優(yōu)勢:

接口雖然提供了缺省方法,但接口仍有有以下局限性:

接口缺省方法的設(shè)計目的和優(yōu)勢在于:

為了接口的演化

可以減少第三方工具類的創(chuàng)建

可以避免創(chuàng)建基類

由于接口的局限性和設(shè)計目的的不同,接口并不能完全替換抽象類。但是通過對接口提供一個抽象的骨架實現(xiàn)類,可以把接口和抽象類的優(yōu)點結(jié)合起來。 接口負(fù)責(zé)定義類型,或許還提供一些缺省方法,而骨架實現(xiàn)類則負(fù)責(zé)實現(xiàn)除基本類型接口方法之外,剩下的非基本類型接口方法。擴(kuò)展骨架實現(xiàn)占了實現(xiàn)接口之外的大部分工作。這就是模板方法(Template Method)設(shè)計模式。

Image [5].png

接口Protocol:定義了RPC協(xié)議層兩個主要的方法,export暴露服務(wù)和refer引用服務(wù)

抽象類AbstractProtocol:封裝了暴露服務(wù)之后的Exporter和引用服務(wù)之后的Invoker實例,并實現(xiàn)了服務(wù)銷毀的邏輯

具體實現(xiàn)類XxxProtocol:實現(xiàn)export暴露服務(wù)和refer引用服務(wù)具體邏輯

由于為了保持Java代碼的兼容性,支持和原生態(tài)類型轉(zhuǎn)換,并使用擦除機(jī)制實現(xiàn)的泛型。但是使用原生態(tài)類型就會失去泛型的優(yōu)勢,會受到編譯器警告。

每一條警告都表示可能在運行時拋出ClassCastException異常。要盡最大的努力去消除這些警告。如果無法消除但是可以證明引起警告的代碼是安全的,就可以在盡可能小的范圍中,使用@SuppressWarnings("unchecked")注解來禁止警告,但是要把禁止的原因記錄下來。

參數(shù)化類型不支持協(xié)變的,即對于任何兩個不同的類型Type1和Type2而言,List既不是List的子類型,也不是它的超類。為了解決這個問題,提高靈活性,Java提供了一種特殊的參數(shù)化類型,稱作有限制的通配符類型,即List? extends E和List? super E。使用原則是producer-extends,consumer-super(PECS)。如果即是生產(chǎn)者,又是消費者,就沒有必要使用通配符了。

還有一種特殊的無限制通配符List?,表示某種類型但不確定。常用作泛型的引用,不可向其添加除Null以外的任何對象。

嵌套類(nested class)是指定義在另一個類的內(nèi)部的類。 嵌套類存在的目的只是為了它的外部類提供服務(wù),如果其他的環(huán)境也會用到的話,應(yīng)該成為一個頂層類(top-level class)。 嵌套類有四種:靜態(tài)成員類(static member class)、非靜態(tài)成員類(nonstatic member class)、匿名類(anonymous class)和 局部類(local class)。除了第一種之外,其他三種都稱為內(nèi)部類(inner class)。

總而言之,這四種嵌套類都有自己的用途。假設(shè)這個嵌套類屬于一個方法的內(nèi)部,如果只需要在一個地方創(chuàng)建實例,并且已經(jīng)有了一個預(yù)置的類型可以說明這個類的特征,就要把它做成匿名類。如果一個嵌套類需要在單個方法之外仍然可見,或者它太長了,不適合放在方法內(nèi)部,就應(yīng)該使用成員類。如果成員類的每個實例都需要一個指向其外圍實例的引用,就要把成員類做成非靜態(tài)的,否則就做成靜態(tài)的。

通過對常見場景的代碼邏輯進(jìn)行抽象封裝,形成相應(yīng)的模板工具類,可以大大減少重復(fù)代碼,專注于業(yè)務(wù)邏輯,提高代碼質(zhì)量。

面向?qū)ο缶幊滔鄬τ诿嫦蜻^程,多了實例化這一步,而對象的創(chuàng)建必須要指定具體類型。我們常見的做法是“哪里用到,就在哪里創(chuàng)建”,使用實例和創(chuàng)建實例的是同一段代碼。這似乎使代碼更具有可讀性,但是某些情況下造成了不必要的耦合。

對于頂層的(非嵌套的)類和接口,只有兩種的訪問級別:包級私有的(沒有public修飾)和公有的(public修飾)。

對于成員(實例/域、方法、嵌套類和嵌套接口)由四種的訪問級別,可訪問性如下遞增:

正確地使用這些修飾符對于實現(xiàn)信息隱藏是非常關(guān)鍵的,原則就是:盡可能地使每個類和成員不被外界訪問(私有或包級私有)。這樣好處就是在以后的發(fā)行版本中,可以對它進(jìn)行修改、替換或者刪除,而無須擔(dān)心會影響現(xiàn)有的客戶端程序。

不可變類是指其實例不能被修改的類。每個實例中包含的所有信息都必須在創(chuàng)建該實例時提供,并在對象的整個生命周期內(nèi)固定不變。不可變類好處就是簡單易用、線程安全、可自由共享而不容易出錯。Java平臺類庫中包含許多不可變的類,比如String、基本類型包裝類、BigDecimal等。

為了使類成為不可變,要遵循下面五條規(guī)則:

可變性最小化的一些建議:

TDD的最終目標(biāo)是整潔可用的代碼(clean code that works)。大多數(shù)的開發(fā)者大部分時間無法得到整潔可用的代碼。辦法是分而治之。首先解決目標(biāo)中的“可用”問題,然后再解決“代碼的整潔”問題。這與體系結(jié)構(gòu)驅(qū)動(architecture-driven)的開發(fā)相反。

采用TDD另一個好處就是讓我們擁有一套伴隨代碼產(chǎn)生的詳盡的自動化測試集。將來無論出于任何原因(需求、重構(gòu)、性能改進(jìn))需要對代碼進(jìn)行維護(hù)時,在這套測試集的驅(qū)動下工作,我們代碼將會一直是健壯的。

Image [6].png

添加一個測試 - 運行所有測試并檢查測試結(jié)果 - 編寫代碼以通過測試 - 運行所有測試且全部通過 - 重構(gòu)代碼,以消除重復(fù)設(shè)計,優(yōu)化設(shè)計結(jié)構(gòu)

作者:VectorJin

java中的開閉原則講的是什么意思

開閉原則,是一種設(shè)計模式,隨著面向?qū)ο蟪绦蛟O(shè)計的思想,應(yīng)運而生。

開,指的是可以在源代碼的基礎(chǔ)上進(jìn)行擴(kuò)展,比如繼承,接口,抽象類等。在JAVA中,之所以用繼承,是在可以直接調(diào)用類庫的前提下,對其功能進(jìn)行擴(kuò)展。不需要應(yīng)用者去了解封裝類的內(nèi)部邏輯就可以做開發(fā)。

閉,指的是原本封裝好的代碼不允許你去更改,比如JDK里面內(nèi)置的Jar包。

Java中的開閉原則是什么意思

開閉原則即封閉對原來代碼的修改,開放對原來代碼的擴(kuò)展(如類的繼承,接口的實現(xiàn)等)

開閉原則是一種設(shè)計思想,并不局限于java語言

大概意思就是這些,但是要真正掌握運用開閉原則,還是要多多實踐,多多體會

JAVA23種設(shè)計模式

設(shè)計模式主要分三個類型:創(chuàng)建型、結(jié)構(gòu)型和行為型。

其中創(chuàng)建型有:

一、Singleton,單例模式:保證一個類只有一個實例,并提供一個訪問它的全局訪問點

二、Abstract Factory,抽象工廠:提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無須指定它們的具體類。

三、Factory Method,工廠方法:定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類,F(xiàn)actory Method使一個類的實例化延遲到了子類。

四、Builder,建造模式:將一個復(fù)雜對象的構(gòu)建與他的表示相分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。

五、Prototype,原型模式:用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型來創(chuàng)建新的對象。

行為型有:

六、Iterator,迭代器模式:提供一個方法順序訪問一個聚合對象的各個元素,而又不需要暴露該對象的內(nèi)部表示。

七、Observer,觀察者模式:定義對象間一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知自動更新。

八、Template Method,模板方法:定義一個操作中的算法的骨架,而將一些步驟延遲到子類中,TemplateMethod使得子類可以不改變一個算法的結(jié)構(gòu)即可以重定義該算法得某些特定步驟。

九、Command,命令模式:將一個請求封裝為一個對象,從而使你可以用不同的請求對客戶進(jìn)行參數(shù)化,對請求排隊和記錄請求日志,以及支持可撤銷的操作。

十、State,狀態(tài)模式:允許對象在其內(nèi)部狀態(tài)改變時改變他的行為。對象看起來似乎改變了他的類。

十一、Strategy,策略模式:定義一系列的算法,把他們一個個封裝起來,并使他們可以互相替換,本模式使得算法可以獨立于使用它們的客戶。

十二、China of Responsibility,職責(zé)鏈模式:使多個對象都有機(jī)會處理請求,從而避免請求的送發(fā)者和接收者之間的耦合關(guān)系

十三、Mediator,中介者模式:用一個中介對象封裝一些列的對象交互。

十四、Visitor,訪問者模式:表示一個作用于某對象結(jié)構(gòu)中的各元素的操作,它使你可以在不改變各元素類的前提下定義作用于這個元素的新操作。

十五、Interpreter,解釋器模式:給定一個語言,定義他的文法的一個表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。

十六、Memento,備忘錄模式:在不破壞對象的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)。

結(jié)構(gòu)型有:

十七、Composite,組合模式:將對象組合成樹形結(jié)構(gòu)以表示部分整體的關(guān)系,Composite使得用戶對單個對象和組合對象的使用具有一致性。

十八、Facade,外觀模式:為子系統(tǒng)中的一組接口提供一致的界面,fa?ade提供了一高層接口,這個接口使得子系統(tǒng)更容易使用。

十九、Proxy,代理模式:為其他對象提供一種代理以控制對這個對象的訪問

二十、Adapter,適配器模式:將一類的接口轉(zhuǎn)換成客戶希望的另外一個接口,Adapter模式使得原本由于接口不兼容而不能一起工作那些類可以一起工作。

二十一、Decrator,裝飾模式:動態(tài)地給一個對象增加一些額外的職責(zé),就增加的功能來說,Decorator模式相比生成子類更加靈活。

二十二、Bridge,橋模式:將抽象部分與它的實現(xiàn)部分相分離,使他們可以獨立的變化。

二十三、Flyweight,享元模式

23種設(shè)計模式要在這里詳細(xì)的都說一遍內(nèi)容實在太多了啊,推薦你一本好書《軟件秘笈:設(shè)計模式那點事》,里面講解的23中設(shè)計模式例子很生動,容易理解,還有JDK中設(shè)計模式應(yīng)用情況,看了收獲挺大的!百度里面搜“設(shè)計模式”,第一條中設(shè)計模式百度百科中就有首推該圖書,瀏覽量在20幾萬以上的,不會錯的。

祝你早日學(xué)會設(shè)計模式!


本文題目:開閉原則java代碼舉例,代碼的開閉原則
分享URL:http://weahome.cn/article/hcihcs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部