RefactoringGuru 代碼異味和重構(gòu)技巧總結(jié)

整理自 RefactoringGuru

代碼異味

——什么悼吱?代碼如何“聞味道”?拜隧?

——它沒(méi)有鼻子...但它肯定會(huì)發(fā)臭西傀!

代碼膨脹

【代碼膨脹】是代碼动猬、方法和類(lèi)虏束,它們的規(guī)模已經(jīng)增加到了難以處理的地步棉饶。通常,這些異味不會(huì)立即出現(xiàn)镇匀,而是隨著程序的演化而積累(尤其是當(dāng)沒(méi)有人努力根除它們的時(shí)候)照藻。

過(guò)長(zhǎng)方法

方法包含的代碼行太多。一般來(lái)說(shuō)坑律,任何超過(guò)十行的方法都會(huì)讓你產(chǎn)生疑問(wèn)岩梳。

過(guò)大的類(lèi)

一個(gè)類(lèi)包含許多字段/方法/代碼行。

基本類(lèi)型偏執(zhí)

在簡(jiǎn)單任務(wù)中使用基本類(lèi)型而不是小對(duì)象(例如貨幣晃择、范圍冀值、電話(huà)號(hào)碼的特殊字符串等)

使用常量來(lái)編碼信息(例如常量USER_ADMIN_ROLE=1表示具有管理員權(quán)限的用戶(hù)。)

在數(shù)據(jù)數(shù)組中使用字符串常量作為字段名宫屠。

過(guò)長(zhǎng)參數(shù)列表

一個(gè)方法有三個(gè)或四個(gè)以上的參數(shù)列疗。

數(shù)據(jù)泥團(tuán)

有時(shí),代碼的不同部分包含相同的變量組(例如用于連接數(shù)據(jù)庫(kù)的參數(shù))浪蹂。這些組應(yīng)該轉(zhuǎn)化為它們自己的類(lèi)抵栈。

面向?qū)ο鬄E用

所有這些異味都是面向?qū)ο缶幊淘淼牟煌暾虿徽_應(yīng)用。

switch語(yǔ)句

你有一個(gè)復(fù)雜的switch運(yùn)算符或if語(yǔ)句序列坤次。

臨時(shí)字段

臨時(shí)字段僅在特定情況下獲取其值(因此對(duì)象需要它)古劲。除此之外,它們是空的缰猴。

被拒絕的繼承

如果子類(lèi)只使用從其父類(lèi)繼承的一些方法和屬性产艾,那么層次結(jié)構(gòu)就不正常。不需要的方法可能只是不使用滑绒,或者被重新定義并發(fā)出異常闷堡。

具有不同接口的備選類(lèi)

兩個(gè)類(lèi)具有相同的函數(shù),但方法名不同疑故。

更改的阻礙

這些異味意味著杠览,如果你需要在代碼的某個(gè)地方更改某些內(nèi)容,那么你也必須在其他地方進(jìn)行許多更改纵势。因此踱阿,程序開(kāi)發(fā)變得更加復(fù)雜和昂貴。

發(fā)散式更改

在更改類(lèi)的時(shí)候钦铁,你發(fā)現(xiàn)自己必須更改許多不相關(guān)的方法扫茅。例如,添加新產(chǎn)品類(lèi)型時(shí)育瓜,必須更改查找葫隙、展示和訂購(gòu)產(chǎn)品的方法。

散彈式更改

修改任何東西都需要對(duì)許多不同的類(lèi)做出許多小的更改躏仇。

平行繼承體系

每當(dāng)你為一個(gè)類(lèi)創(chuàng)建一個(gè)子類(lèi)時(shí)恋脚,你就會(huì)發(fā)現(xiàn)自己需要為另一個(gè)類(lèi)創(chuàng)建一個(gè)子類(lèi)。

可有可無(wú)的東西

可有可無(wú)的東西是毫無(wú)意義和不必要的焰手,如果沒(méi)有它糟描,代碼就會(huì)更干凈、更高效书妻、更容易理解船响。

注釋

方法中充滿(mǎn)了解釋性注釋。

重復(fù)代碼

兩段代碼看起來(lái)幾乎相同。

冗余類(lèi)

理解和維護(hù)類(lèi)總是需要花費(fèi)時(shí)間和金錢(qián)见间。因此聊闯,如果一個(gè)類(lèi)不足以吸引你的注意力,它應(yīng)該被刪除米诉。

數(shù)據(jù)類(lèi)

數(shù)據(jù)類(lèi)是指只包含字段和用于訪(fǎng)問(wèn)字段的方法(獲取器和設(shè)置器)的類(lèi)菱蔬。這些只是其他類(lèi)使用的數(shù)據(jù)容器。這些類(lèi)不包含任何附加功能史侣,并且不能獨(dú)立操作它們所擁有的數(shù)據(jù)拴泌。

死代碼

變量、參數(shù)惊橱、字段蚪腐、方法或類(lèi)已不再使用(通常是因?yàn)樗堰^(guò)時(shí))。

夸大通用性

存在未使用的類(lèi)税朴、方法削茁、字段或參數(shù)。

耦合器

這一組中的所有異味都會(huì)導(dǎo)致類(lèi)之間的過(guò)度耦合掉房,或者顯示如果耦合被過(guò)度委托所取代會(huì)發(fā)生什么茧跋。

功能依賴(lài)

一個(gè)方法訪(fǎng)問(wèn)另一個(gè)對(duì)象的數(shù)據(jù)多于它自己的數(shù)據(jù)。

過(guò)度親密

一個(gè)類(lèi)使用另一個(gè)類(lèi)的內(nèi)部字段和方法卓囚。

消息鏈

在代碼中可以看到一系列類(lèi)似于$a->b()->c()->d()的調(diào)用瘾杭。

中間人

如果一個(gè)類(lèi)只執(zhí)行一個(gè)操作,將工作委托給另一個(gè)類(lèi)哪亿,那么它為什么存在呢粥烁?

其他異味

不完善的庫(kù)類(lèi)

庫(kù)遲早會(huì)停止?jié)M足用戶(hù)需求。由于庫(kù)是只讀的蝇棉,所以問(wèn)題的唯一解決方案讨阻,也就是更改庫(kù),通常是不可能的篡殷。

重構(gòu)技巧

組合方法

很多重構(gòu)都致力于正確地組合方法钝吮。在大多數(shù)情況下,過(guò)長(zhǎng)的方法是萬(wàn)惡之源板辽。這些方法中變幻莫測(cè)的代碼隱藏了執(zhí)行邏輯奇瘦,使得該方法極難理解,甚至更難更改劲弦。

這一組中的重構(gòu)技巧簡(jiǎn)化了方法耳标,消除了代碼重復(fù),并為未來(lái)的改進(jìn)鋪平了道路邑跪。

提取方法

問(wèn)題:你有一個(gè)可以組合在一起的代碼片段次坡。

解決方案:將此代碼移動(dòng)到一個(gè)單獨(dú)的新方法(或函數(shù))呼猪,并用對(duì)該方法的調(diào)用替換舊代碼。

內(nèi)聯(lián)函數(shù)

問(wèn)題:當(dāng)方法主體比方法本身更明顯時(shí)砸琅,請(qǐng)使用此技巧宋距。

解決方案:用方法的內(nèi)容替換對(duì)方法的調(diào)用,并刪除方法本身明棍。

提取變量

問(wèn)題:你的表達(dá)式很難理解乡革。

解決方案:將表達(dá)式或其部分的結(jié)果放在獨(dú)立的變量中寇僧,這些變量是自解釋的摊腋。

內(nèi)聯(lián)臨時(shí)變量

問(wèn)題:你有一個(gè)臨時(shí)變量,它被分配了一個(gè)簡(jiǎn)單表達(dá)式的結(jié)果嘁傀,僅此而已兴蒸。

解決方案:用表達(dá)式本身替換對(duì)變量的引用。

用查詢(xún)替換臨時(shí)變量

問(wèn)題:將表達(dá)式的結(jié)果放在局部變量中细办,以便以后在代碼中使用橙凳。

解決方案:將整個(gè)表達(dá)式移動(dòng)到一個(gè)單獨(dú)的方法,并從中返回結(jié)果笑撞。查詢(xún)方法岛啸,而不是使用變量。如有必要茴肥,在其他方法中加入新方法坚踩。

拆分臨時(shí)變量

問(wèn)題:你有一個(gè)局部變量,用于在方法中存儲(chǔ)各種中間值(循環(huán)變量除外)瓤狐。

解決方案:對(duì)不同的值使用不同的變量瞬铸。每個(gè)變量應(yīng)該只負(fù)責(zé)一個(gè)特定的事情。

移除參數(shù)賦值

問(wèn)題:某些值被賦給了方法體中的參數(shù)础锐。

解決方案:使用局部變量而不是參數(shù)嗓节。

用方法對(duì)象替換方法

問(wèn)題:你有一個(gè)很長(zhǎng)的方法,其中局部變量相互交織皆警,以至于你不能應(yīng)用【提取方法】拦宣。

解決方案:將該方法轉(zhuǎn)換為一個(gè)單獨(dú)的類(lèi),以便局部變量成為該類(lèi)的字段信姓。然后可以將該方法拆分為同一類(lèi)中的多個(gè)方法恢着。

替代算法

問(wèn)題:所以你想用一個(gè)新的算法替換現(xiàn)有的算法?

解決方案:用新算法替換實(shí)現(xiàn)算法的方法體财破。

在對(duì)象間移動(dòng)功能

即使你在不同的類(lèi)之間掰派,以不太完美的方式分布了功能,仍然存在希望左痢。

這些重構(gòu)技術(shù)展示了如何在類(lèi)之間安全地移動(dòng)功能靡羡,創(chuàng)建新的類(lèi)系洛,以及隱藏實(shí)現(xiàn)細(xì)節(jié)以防公開(kāi)訪(fǎng)問(wèn)。

移動(dòng)方法

問(wèn)題:一個(gè)方法在另一個(gè)類(lèi)中使用的次數(shù)多于在它自己的類(lèi)中使用的次數(shù)略步。

解決方案:在使用該方法最多的類(lèi)中創(chuàng)建一個(gè)新方法描扯,然后將代碼從舊方法移動(dòng)到這里。將舊方法的代碼轉(zhuǎn)換為對(duì)另一個(gè)類(lèi)中新方法的引用趟薄,或者將其完全刪除绽诚。

移動(dòng)字段

問(wèn)題:一個(gè)字段在另一個(gè)類(lèi)中使用的次數(shù)比在它自己的類(lèi)中使用的次數(shù)多。

解決方案:在新類(lèi)中創(chuàng)建一個(gè)字段杭煎,并將舊字段的所有使用重定向到該字段恩够。

提取類(lèi)

問(wèn)題:當(dāng)一個(gè)類(lèi)做兩個(gè)類(lèi)的工作時(shí),會(huì)非常笨拙羡铲。

解決方案:相反蜂桶,創(chuàng)建一個(gè)新類(lèi),并將負(fù)責(zé)相關(guān)功能的字段和方法放在其中也切。

內(nèi)聯(lián)類(lèi)

問(wèn)題:一個(gè)類(lèi)幾乎什么都不做扑媚,也不負(fù)責(zé)任何事情,也沒(méi)有為它規(guī)劃額外的責(zé)任雷恃。

解決方案:將所有功能從該類(lèi)移動(dòng)到另一個(gè)類(lèi)疆股。

隱藏委托關(guān)系

問(wèn)題:客戶(hù)端從對(duì)象 A 的字段或方法中獲取對(duì)象 B。然后客戶(hù)端調(diào)用對(duì)象 B 的方法倒槐。

解決方案:在類(lèi) A 中創(chuàng)建一個(gè)新方法旬痹,將調(diào)用委托給對(duì)象 B。現(xiàn)在客戶(hù)端不知道也不依賴(lài)于類(lèi) B导犹。

移除中間人

問(wèn)題:一個(gè)類(lèi)有太多的方法唱凯,這些方法只是委托給其他對(duì)象。

解決方案:刪除這些方法谎痢,并強(qiáng)制客戶(hù)端直接調(diào)用最終方法磕昼。

引入外部方法

問(wèn)題:實(shí)用程序類(lèi)不包含所需的方法,并且無(wú)法將該方法添加到該類(lèi)中节猿。

解決方案:將該方法添加到客戶(hù)端類(lèi)票从,并將實(shí)用程序類(lèi)的對(duì)象作為參數(shù)傳遞給它。

引入本地?cái)U(kuò)展

問(wèn)題:實(shí)用程序類(lèi)不包含你需要的某些方法滨嘱。但不能將這些方法添加到類(lèi)中峰鄙。

解決方案:創(chuàng)建一個(gè)包含這些方法的新類(lèi),并使其成為實(shí)用程序類(lèi)的子類(lèi)或包裝器太雨。

組織數(shù)據(jù)

這些重構(gòu)技術(shù)有助于數(shù)據(jù)處理吟榴,用豐富的類(lèi)功能替換基本類(lèi)型。

另一個(gè)重要的結(jié)果是解開(kāi)了類(lèi)的關(guān)聯(lián)囊扳,這使得類(lèi)更具可移植性和可重用性吩翻。

自封裝字段

問(wèn)題:你直接訪(fǎng)問(wèn)類(lèi)內(nèi)的私有字段兜看。

解決方案:為字段創(chuàng)建一個(gè)獲取器和設(shè)置器,并僅使用它們?cè)L問(wèn)字段狭瞎。

用對(duì)象替換數(shù)據(jù)值

問(wèn)題:一個(gè)類(lèi)(或一組類(lèi))包含一個(gè)數(shù)據(jù)字段细移。該字段有自己的行為和相關(guān)數(shù)據(jù)。

解決方案:創(chuàng)建一個(gè)新類(lèi)熊锭,將舊字段及其行為放在該類(lèi)中弧轧,并將該類(lèi)的對(duì)象存儲(chǔ)在原始類(lèi)中。

將值更改為引用

問(wèn)題:所以你有單個(gè)類(lèi)的許多相同實(shí)例碗殷,并需要用單個(gè)對(duì)象替換它精绎。

解決方案:將相同的對(duì)象轉(zhuǎn)換為單個(gè)引用對(duì)象。

將引用更改為值

問(wèn)題:你有一個(gè)太小且很少更改的引用對(duì)象亿扁,因此無(wú)法管理其生命周期捺典。

解決方案:將其轉(zhuǎn)化為值對(duì)象鸟廓。

用對(duì)象替換數(shù)組

問(wèn)題:你有一個(gè)包含各種類(lèi)型數(shù)據(jù)的數(shù)組从祝。

解決方案:將數(shù)組替換為每個(gè)元素都有單獨(dú)字段的對(duì)象。

重復(fù)的被觀(guān)測(cè)數(shù)據(jù)

問(wèn)題:存儲(chǔ)在類(lèi)中的領(lǐng)域數(shù)據(jù)是否負(fù)責(zé)GUI引谜?

解決方案:那么最好將數(shù)據(jù)分成不同的類(lèi)牍陌,確保領(lǐng)域類(lèi)和GUI之間的連接和同步。

將單向關(guān)聯(lián)改為雙向關(guān)聯(lián)

問(wèn)題:你有兩個(gè)類(lèi)员咽,每個(gè)類(lèi)都需要使用另一個(gè)類(lèi)的功能毒涧,但它們之間的關(guān)聯(lián)只是單向的。

解決方案:將缺少的關(guān)聯(lián)添加到需要它的類(lèi)中贝室。

將雙向關(guān)聯(lián)改為單向關(guān)聯(lián)

問(wèn)題:類(lèi)之間存在雙向關(guān)聯(lián)契讲,但其中一個(gè)類(lèi)不使用另一個(gè)類(lèi)的功能。

解決方案:刪除未使用的關(guān)聯(lián)滑频。

用符號(hào)常量替換幻數(shù)

問(wèn)題:你的代碼使用了一個(gè)具有特定含義的數(shù)字捡偏。

解決方案:將這個(gè)數(shù)字替換為一個(gè)常量,該常量有一個(gè)人類(lèi)可讀的名稱(chēng)來(lái)解釋數(shù)字的含義峡迷。

封裝字段

問(wèn)題:你有一個(gè)公共字段银伟。

解決方案:將字段設(shè)置為私有,并為其創(chuàng)建訪(fǎng)問(wèn)方法绘搞。

封裝集合

問(wèn)題:一個(gè)類(lèi)包含一個(gè)集合字段和一個(gè)用于處理集合的簡(jiǎn)單獲取器和設(shè)置器彤避。

解決方案:將獲取器的返回值設(shè)為只讀,并創(chuàng)建用于添加/刪除集合元素的方法夯辖。

用類(lèi)替換類(lèi)型代碼

問(wèn)題:一個(gè)類(lèi)有一個(gè)包含類(lèi)型代碼的字段琉预。這種類(lèi)型的值不用于運(yùn)算符條件,也不會(huì)影響程序的行為蒿褂。

解決方案:創(chuàng)建一個(gè)新類(lèi)圆米,并使用其對(duì)象而不是類(lèi)型代碼的值尖阔。

用子類(lèi)替換類(lèi)型代碼

問(wèn)題:你有一個(gè)直接影響程序行為的代碼類(lèi)型(此字段的值觸發(fā)條件中的各種代碼)。

解決方案:為代碼類(lèi)型的每個(gè)值創(chuàng)建子類(lèi)榨咐。然后將相關(guān)行為從原始類(lèi)提取到這些子類(lèi)中介却。用多態(tài)替換控制流代碼。

用狀態(tài)/策略替換類(lèi)型代碼

問(wèn)題:你有一個(gè)影響行為的代碼類(lèi)型块茁,但不能使用子類(lèi)來(lái)消除它齿坷。

解決方案:用狀態(tài)對(duì)象替換類(lèi)型代碼。如果需要用類(lèi)型代碼替換字段值数焊,則另一個(gè)狀態(tài)對(duì)象為“已插入”永淌。

用字段替換子類(lèi)

問(wèn)題:你的子類(lèi)只在(常量返回)方法上有所不同。

解決方案:用父類(lèi)中的字段替換方法佩耳,并刪除子類(lèi)遂蛀。

簡(jiǎn)化條件表達(dá)式

隨著時(shí)間的推移,條件的邏輯往往變得越來(lái)越復(fù)雜干厚,還有更多的技術(shù)可以解決這個(gè)問(wèn)題李滴。

分解條件

問(wèn)題:你有一個(gè)復(fù)雜的條件(if-then/elseswitch)。

解決方案:將條件的復(fù)雜部分分解為單獨(dú)的方法:條件蛮瞄、thenelse所坯。

合并條件表達(dá)式

問(wèn)題:你有多個(gè)條件產(chǎn)生相同的結(jié)果或操作。

解決方案:將所有這些條件合并到一個(gè)表達(dá)式中挂捅。

合并重復(fù)的條件片段

問(wèn)題:在條件語(yǔ)句的所有分支中都可以找到相同的代碼芹助。

解決方案:將代碼移到條件之外。

移除控制標(biāo)志

問(wèn)題:有一個(gè)布爾變量充當(dāng)多個(gè)布爾表達(dá)式的控制標(biāo)志闲先。

解決方案:使用break状土、continuereturn代替變量。

使用守衛(wèi)子句來(lái)代替嵌套的條件判斷

問(wèn)題:有一組嵌套的條件伺糠,很難確定代碼執(zhí)行的正常流程蒙谓。

解決方案:將所有特殊檢查和邊界情況隔離到單獨(dú)的子句中,并將其放在主要檢查之前退盯。理想情況下彼乌,你應(yīng)該有一個(gè)條件列表,一個(gè)接一個(gè)渊迁。

用多態(tài)替換條件

問(wèn)題:你有一個(gè)條件慰照,根據(jù)對(duì)象類(lèi)型或?qū)傩詧?zhí)行各種操作。

解決方案:創(chuàng)建與條件的分支相匹配的子類(lèi)琉朽。在它們中毒租,創(chuàng)建一個(gè)共享方法,并將代碼從條件的相應(yīng)分支移動(dòng)到它箱叁。然后用相關(guān)的方法調(diào)用替換條件墅垮。結(jié)果是惕医,根據(jù)對(duì)象類(lèi),可以通過(guò)多態(tài)實(shí)現(xiàn)正確的實(shí)現(xiàn)算色。

引入空對(duì)象

問(wèn)題:由于一些方法返回null而不是真實(shí)對(duì)象抬伺,所以在代碼中有很多null檢查。

解決方案:返回一個(gè)顯示默認(rèn)行為的空對(duì)象灾梦,而不是null峡钓。

引入斷言

問(wèn)題:要使部分代碼正常工作,某些條件或值必須為true若河。

解決方案:用特定的斷言檢查替換這些假設(shè)能岩。

簡(jiǎn)化方法調(diào)用

這些技術(shù)使方法調(diào)用更簡(jiǎn)單、更容易理解萧福。這反過(guò)來(lái)簡(jiǎn)化了用于類(lèi)之間交互的接口拉鹃。

重命名方法

問(wèn)題:方法的名稱(chēng)不能解釋該方法的功能。

解決方案:重命名該方法鲫忍。

添加參數(shù)

問(wèn)題:方法沒(méi)有足夠的數(shù)據(jù)來(lái)執(zhí)行某些操作膏燕。

解決方案:創(chuàng)建一個(gè)新參數(shù)來(lái)傳遞必要的數(shù)據(jù)。

刪除參數(shù)

問(wèn)題:方法體中沒(méi)有使用某個(gè)參數(shù)饲窿。

解決方案:刪除未使用的參數(shù)煌寇。

將查詢(xún)與修改分開(kāi)

問(wèn)題:是否有一個(gè)方法可以返回一個(gè)值焕蹄,但也可以更改對(duì)象內(nèi)部的某些內(nèi)容逾雄?

解決方案:將該方法分為兩種不同的方法。正如你所料腻脏,其中一個(gè)應(yīng)該返回值鸦泳,另一個(gè)則修改對(duì)象。

將方法參數(shù)化

問(wèn)題:多個(gè)方法執(zhí)行類(lèi)似的操作永品,這些操作只在其內(nèi)部值做鹰、數(shù)字或操作上有所不同。

解決方案:通過(guò)使用一個(gè)將傳遞必要特殊值的參數(shù)來(lái)組合這些方法鼎姐。

用顯式方法替換參數(shù)

問(wèn)題:一個(gè)方法被分成幾個(gè)部分钾麸,每個(gè)部分的運(yùn)行取決于一個(gè)參數(shù)的值。

解決方案:將方法的各個(gè)部分提取到它們自己的方法中炕桨,并調(diào)用它們饭尝,而不是原始方法。

保存整個(gè)對(duì)象

問(wèn)題:從一個(gè)對(duì)象中獲取多個(gè)值献宫,然后將它們作為參數(shù)傳遞給一個(gè)方法钥平。

解決方案:相反,嘗試傳遞整個(gè)對(duì)象姊途。

用方法調(diào)用替換參數(shù)

問(wèn)題:調(diào)用一個(gè)查詢(xún)方法并將其結(jié)果作為參數(shù)傳遞給另一個(gè)方法涉瘾,而該方法可以直接調(diào)用該查詢(xún)知态。

解決方案:不要通過(guò)參數(shù)傳遞值,而是嘗試在方法體中放置一個(gè)查詢(xún)調(diào)用立叛。

引入?yún)?shù)對(duì)象

問(wèn)題:你的方法包含一組重復(fù)的參數(shù)负敏。

解決方案:用對(duì)象替換這些參數(shù)。

移除設(shè)置方法

問(wèn)題:字段的值應(yīng)該只在創(chuàng)建時(shí)設(shè)置秘蛇,之后任何時(shí)候都不能更改原在。

解決方案:刪除設(shè)置字段值的方法。

隱藏方法

問(wèn)題:一個(gè)方法不被其他類(lèi)使用彤叉,或者只在它自己的類(lèi)層次結(jié)構(gòu)中使用庶柿。

解決方案:將方法設(shè)置為私有或受保護(hù)。

用工廠(chǎng)方法代替構(gòu)造器

問(wèn)題:你有一個(gè)復(fù)雜的構(gòu)造器秽浇,它的功能不僅僅是在對(duì)象字段中設(shè)置參數(shù)值浮庐。

解決方案:創(chuàng)建一個(gè)工廠(chǎng)方法并使用它替換構(gòu)造器調(diào)用。

用異常替換錯(cuò)誤代碼

問(wèn)題:方法返回指示錯(cuò)誤的特殊值柬焕?

解決方案:拋出一個(gè)異常审残。

用測(cè)試替換異常

問(wèn)題:在一個(gè)簡(jiǎn)單的測(cè)試就能完成任務(wù)的地方拋出異常?

解決方案:用條件測(cè)試替換異常斑举。

處理泛化

抽象有自己的一組重構(gòu)技術(shù)搅轿,主要關(guān)于沿著類(lèi)繼承層次結(jié)構(gòu)移動(dòng)功能、創(chuàng)建新的類(lèi)和接口富玷、用委托代替繼承以及相反璧坟。

上移字段

問(wèn)題:兩個(gè)類(lèi)具有相同的字段。

解決方案:從子類(lèi)中刪除字段赎懦,并將其移動(dòng)到超類(lèi)雀鹃。

上移方法

問(wèn)題:你的子類(lèi)具有執(zhí)行類(lèi)似工作的方法。

解決方案:使方法相同励两,然后將它們移動(dòng)到相關(guān)的超類(lèi)黎茎。

上移構(gòu)造器主體

問(wèn)題:你的子類(lèi)的構(gòu)造器的代碼基本相同。

解決方案:創(chuàng)建一個(gè)超類(lèi)構(gòu)造器当悔,并將子類(lèi)中相同的代碼移動(dòng)到它傅瞻。在子類(lèi)構(gòu)造器中調(diào)用超類(lèi)構(gòu)造器。

下移方法

問(wèn)題:超類(lèi)中實(shí)現(xiàn)的行為是僅由一個(gè)(或幾個(gè))子類(lèi)使用的嗎盲憎?

解決方案:將此行為移動(dòng)到子類(lèi)嗅骄。

下移字段

問(wèn)題:字段是否僅用于少數(shù)子類(lèi)?

解決方案:將字段移動(dòng)到這些子類(lèi)焙畔。

提取子類(lèi)

問(wèn)題:某個(gè)類(lèi)具有僅在某些情況下使用的功能掸读。

解決方案:創(chuàng)建一個(gè)子類(lèi),并在這些情況下使用它。

提取超類(lèi)

問(wèn)題:有兩個(gè)類(lèi)具有相同的字段和方法儿惫。

解決方案:為它們創(chuàng)建一個(gè)共享超類(lèi)柳刮,并將所有相同的字段和方法移動(dòng)到其中嫩挤。

提取接口

問(wèn)題:多個(gè)客戶(hù)端使用類(lèi)接口的同一部分肢执。另一種情況:兩個(gè)類(lèi)中的部分接口是相同的贴浙。

解決方案:將這個(gè)相同的部分移動(dòng)到它自己的接口。

折疊層次結(jié)構(gòu)

問(wèn)題:你有一個(gè)類(lèi)層次結(jié)構(gòu)铛铁,其中一個(gè)子類(lèi)實(shí)際上與其超類(lèi)相同隔显。

解決方案:合并子類(lèi)和超類(lèi)。

形成模板方法

問(wèn)題:你的子類(lèi)實(shí)現(xiàn)的算法包含順序相同的類(lèi)似步驟饵逐。

解決方案:將算法結(jié)構(gòu)和相同的步驟移動(dòng)到一個(gè)超類(lèi)括眠,并將不同步驟的實(shí)現(xiàn)留在子類(lèi)中。

用委托替換繼承

問(wèn)題:有一個(gè)子類(lèi)只使用其超類(lèi)的一部分方法(或者不可能繼承超類(lèi)數(shù)據(jù))倍权。

解決方案:創(chuàng)建一個(gè)字段并在其中放置一個(gè)超類(lèi)對(duì)象掷豺,將方法委托給超類(lèi)對(duì)象,并擺脫繼承薄声。

用繼承替換委托

問(wèn)題:一個(gè)類(lèi)包含許多簡(jiǎn)單的方法当船,這些方法將委托給另一個(gè)類(lèi)的所有方法。

解決方案:使該類(lèi)繼承另一個(gè)類(lèi)默辨,這樣就不需要委托方法德频。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市缩幸,隨后出現(xiàn)的幾起案子壹置,更是在濱河造成了極大的恐慌,老刑警劉巖桌粉,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒸绩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡铃肯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)传蹈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)押逼,“玉大人,你說(shuō)我怎么就攤上這事惦界√舾瘢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵沾歪,是天一觀(guān)的道長(zhǎng)漂彤。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么挫望? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任立润,我火速辦了婚禮,結(jié)果婚禮上媳板,老公的妹妹穿的比我還像新娘桑腮。我一直安慰自己,他們只是感情好蛉幸,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布破讨。 她就那樣靜靜地躺著,像睡著了一般奕纫。 火紅的嫁衣襯著肌膚如雪提陶。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,337評(píng)論 1 310
  • 那天匹层,我揣著相機(jī)與錄音搁骑,去河邊找鬼。 笑死又固,一個(gè)胖子當(dāng)著我的面吹牛仲器,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仰冠,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼乏冀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了洋只?” 一聲冷哼從身側(cè)響起辆沦,我...
    開(kāi)封第一講書(shū)人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎识虚,沒(méi)想到半個(gè)月后肢扯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡担锤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年蔚晨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肛循。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铭腕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出多糠,到底是詐尸還是另有隱情累舷,我是刑警寧澤,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布夹孔,位于F島的核電站被盈,受9級(jí)特大地震影響析孽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜只怎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一袜瞬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧尝盼,春花似錦吞滞、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至赴精,卻和暖如春佩捞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蕾哟。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工一忱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谭确。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓帘营,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逐哈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子芬迄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容