整理自 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/else
或switch
)。
解決方案:將條件的復(fù)雜部分分解為單獨(dú)的方法:條件蛮瞄、then
和else
所坯。
合并條件表達(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
状土、continue
和return
代替變量。
使用守衛(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)默辨,這樣就不需要委托方法德频。