重構(gòu)——在對象之間搬移特性

在對對象的設(shè)計過程中栈暇,“決定把責(zé)任放在哪兒”即使不是最重要的事馆蠕,也是最重要的事情之一涝桅。

1 Move Method

<b>在該函數(shù)最常引用的類中建立一個有著類似行為的新函數(shù)闷游,將舊函數(shù)變成一個單純的委托函數(shù),或是將舊函數(shù)完全移除贴汪。</b>
  <b>Motivation:</b>函數(shù)遷移是重構(gòu)理論的支柱脐往。如果一個類有太多行為,或如果一個類和另一個類有太多合作而形成高度耦合扳埂,就需要搬移函數(shù)业簿。一般在如下情況下需要搬移函數(shù):使用另一個對象的次數(shù)比使用自己所駐對象的次數(shù)還多。
  <b>Routinue:</b>

  • 檢查源類中被源函數(shù)所使用的一切特性阳懂,考慮它們是否需要被搬移梅尤。
  • 檢查源類的子類和超類,看看是否有該函數(shù)的其他聲明岩调。
  • 在目標(biāo)函數(shù)中聲明這個函數(shù)巷燥。
  • 將源函數(shù)的代碼復(fù)制到目標(biāo)函數(shù)中。調(diào)整以保證可運(yùn)行号枕。
  • 編譯目標(biāo)類缰揪。
  • 決定如何從源函數(shù)正確引用目標(biāo)對象。
  • 修改源函數(shù)葱淳,使他成為一個委托函數(shù)钝腺。
  • 編譯抛姑,測試。
  • 決定是否刪除源函數(shù)艳狐,或?qū)⑺鳛橐粋€委托函數(shù)保留下來定硝。
  • 如果要移除源函數(shù),請將源類中對源函數(shù)的所有調(diào)用毫目,替換為對目標(biāo)函數(shù)的調(diào)用蔬啡。
  • 編譯,測試蒜茴。

2 Move Field

<b>在目標(biāo)類新建一個字段星爪,修改源字段的所有用戶,令它們改用新字段粉私。</b>
Motivation:如果一個字段顽腾,在其所駐類之外的另一個類中有更多函數(shù)使用它,就會考慮搬移這個字段诺核。
Routinue:

  • 如果字段的訪問級是public抄肖,使用Encapsulate Field將它封裝起來。
  • 編譯測試窖杀。
  • 在目標(biāo)類中建立與源相同的字段漓摩,并同時建立相應(yīng)的設(shè)值/取值函數(shù)。
  • 編譯目標(biāo)類入客。
  • 決定如何在源對象中引用目標(biāo)對象管毙。
  • 刪除原字段。
  • 將所有對原字段的引用替換為對某個目標(biāo)函數(shù)的調(diào)用桌硫。
  • 編譯夭咬,測試。

3 Extract Class

建立一個新類铆隘,將相關(guān)的字段和函數(shù)從舊類搬移到新類卓舵。
Motivation:一個類應(yīng)該是一個清楚的抽象,處理一些明確的責(zé)任膀钠。這時候就需要切分類出子類掏湾。
Routinue:

  • 決定如何分解類所負(fù)的責(zé)任。
  • 建立一個新類肿嘲,用以表現(xiàn)從舊類中分離出來的責(zé)任融击。
  • 建立“從舊類訪問新類”的連接關(guān)系。
  • 對于每一個想要搬移的字段雳窟,使用Move Field搬移砚嘴。
  • 每次搬移后,編譯、測試际长。
  • 使用Move Method將必要函數(shù)搬移到新類耸采。先搬移較低層次函數(shù)(被調(diào)用多的函數(shù)),再搬移較高層次函數(shù)工育。
  • 每次搬移之后虾宇,編譯、測試如绸。
  • 檢查嘱朽,精簡每個類的接口。
  • 決定是否公開新類怔接。如果你的確需要公開它搪泳,就要決定讓它成為引用對象還是不可變的值對象。

4 Inline Class

將一個類的所有特性移動到另一個類中扼脐,并移除源類岸军。
Motivation:與Extract Class相反。如果一個類不再承擔(dān)足夠的責(zé)任瓦侮、不再有單獨(dú)存在的理由艰赞,將之融入另一個類。

5 Hide Delegate(隱藏“委托關(guān)系”)

在服務(wù)類上建立客戶所需的所有函數(shù)肚吏,用以隱藏委托關(guān)系方妖。
Motivation:為了更好地實現(xiàn)封裝特性,如果客戶通過服務(wù)對象獲得另一個對象罚攀,這就導(dǎo)致了客戶必須知道這種委托關(guān)系党觅,那么當(dāng)委托關(guān)系發(fā)生關(guān)系了,客戶也要相應(yīng)變化斋泄。將委托關(guān)系隱藏起來杯瞻,從而可以去除這種依賴。
Routinue:

  • 對于每一個委托關(guān)系的函數(shù)是己,在服務(wù)對象端建立一個簡單的委托函數(shù)又兵。
  • 調(diào)整客戶任柜,令它只調(diào)用服務(wù)對象提供的函數(shù)卒废。
  • 每次調(diào)整后,編譯并測試宙地。
  • 如果獎勵啊不再有任何客戶需要摔认,變移除服務(wù)對象中的相關(guān)訪問函數(shù)。
  • 編譯宅粥,測試参袱。

6 Remove Middle Man(移動中間人)

讓客戶直接調(diào)用委托類。
Motivation:委托的代價是,委托對象的變化會引起服務(wù)器對象變化抹蚀。當(dāng)服務(wù)類完成成了委托類的中間人剿牺,那么請刪除中間人吧!Don't Be Afraid环壤!不斷使用Hide Delegate和Move Middle Man調(diào)整程序結(jié)構(gòu)晒来。
Routinue:

  • 建立函數(shù),用以獲得受托對象郑现。
  • 對于每個委托函數(shù)湃崩,在服務(wù)類中刪除該函數(shù),并讓需要調(diào)用該函數(shù)的客戶轉(zhuǎn)為調(diào)用受托對象接箫。
  • 處理每個委托函數(shù)后攒读,編譯、測試辛友。

7 Introduce Foreign Method(引入外加函數(shù))

在客戶類中建立一個函數(shù)薄扁,并以第一參數(shù)形式傳入一個服務(wù)類實例。
Motivation:根據(jù)單一職責(zé)原則瞎领,好的編程框架泌辫,往往類的職責(zé)是單一的,那么當(dāng)需要其他的功能的時候九默。重復(fù)代碼是萬惡之源震放!不應(yīng)該無線外加函數(shù)。
Routinue:

  • 在客戶類中建立一個函數(shù)驼修,用來提供你需要的功能殿遂。
  • 以服務(wù)類實例作為該函數(shù)的第一個參數(shù)。
  • 將該函數(shù)注釋為:“外加函數(shù)乙各,應(yīng)在服務(wù)類實現(xiàn)墨礁。”

8 Introduce Local Extension(引入本地擴(kuò)展)

建立一個新類耳峦,使它包含這些額外函數(shù)恩静。讓這個擴(kuò)展品成為源類的子類或包裝類。
Motivation:類作者蹲坷,包括自己都無法預(yù)知未來驶乾。所以往往沒有需要的接口。當(dāng)然我們可以使用Foreign Method循签,然如果需要的額外函數(shù)過多级乐,外加函數(shù)就很難控制了。這時候需要將函數(shù)組織起來县匠,有兩種標(biāo)準(zhǔn)技術(shù)——子類化和包裝风科。這成為本地擴(kuò)展撒轮。也就是在原來的基礎(chǔ)上加入新的特性。

  • 建立一個擴(kuò)展類贼穆,將它作為原始類的子類或包裝類题山。
  • 在擴(kuò)展類中加入轉(zhuǎn)型構(gòu)造函數(shù)。即以源對象為參數(shù)的構(gòu)造函數(shù)故痊。如果用的是子類化方案臀蛛,則應(yīng)該調(diào)用超類構(gòu)造函數(shù);如果是包裝的方案崖蜜,則應(yīng)該作為實例保存起來浊仆,用作接收委托的源對象。
  • 在擴(kuò)展類中加入新特性豫领。
  • 根據(jù)需要抡柿,將原對象替換為擴(kuò)展對象。
  • 將針對原始類定義的所有外加函數(shù)搬移到擴(kuò)展類中等恐。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洲劣,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子课蔬,更是在濱河造成了極大的恐慌囱稽,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件二跋,死亡現(xiàn)場離奇詭異战惊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)扎即,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門吞获,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谚鄙,你說我怎么就攤上這事各拷。” “怎么了闷营?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵烤黍,是天一觀的道長。 經(jīng)常有香客問我傻盟,道長速蕊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任莫杈,我火速辦了婚禮互例,結(jié)果婚禮上奢入,老公的妹妹穿的比我還像新娘筝闹。我一直安慰自己媳叨,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布关顷。 她就那樣靜靜地躺著糊秆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪议双。 梳的紋絲不亂的頭發(fā)上痘番,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機(jī)與錄音平痰,去河邊找鬼汞舱。 笑死,一個胖子當(dāng)著我的面吹牛宗雇,可吹牛的內(nèi)容都是我干的昂芜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼赔蒲,長吁一口氣:“原來是場噩夢啊……” “哼泌神!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起舞虱,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤欢际,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后矾兜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體损趋,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年椅寺,在試婚紗的時候發(fā)現(xiàn)自己被綠了舶沿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡配并,死狀恐怖括荡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情溉旋,我是刑警寧澤畸冲,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站观腊,受9級特大地震影響邑闲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梧油,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一苫耸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧儡陨,春花似錦褪子、人聲如沸量淌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呀枢。三九已至,卻和暖如春笼痛,著一層夾襖步出監(jiān)牢的瞬間裙秋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工缨伊, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留摘刑,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓刻坊,卻偏偏與公主長得像泣侮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子紧唱,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

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

  • 《重構(gòu)》讀書筆記 總覽 第一部分 第一章從實例程序出發(fā)活尊,展示設(shè)計的缺陷,對其重構(gòu)可以了解重構(gòu)的過程和方法漏益。 第二部...
    白樺葉閱讀 2,378評論 2 5
  • 1 Self Encapsulate Field(自封裝字段) 直接訪問一個字段蛹锰,會導(dǎo)致字段之間的的耦合關(guān)系過于笨...
    hklbird閱讀 525評論 0 0
  • 決定把責(zé)任放在哪兒,即使不是最重要的事情, 也是最重要的事之一. Move Method和Move Field簡單...
    rxdxxxx閱讀 274評論 0 0
  • 常在塔中掃心塵,只待一日現(xiàn)天真绰疤,偶見和光同塵智铜犬,從此念念光明生。 原創(chuàng)作品 (Original Article)
    一詩一境界閱讀 312評論 0 0
  • 文/小葉 前言 有許多染房轻庆,可以染出很美的顏色癣猾,有的始終要褪色,于是沾染越多余爆,極少數(shù)的染不上外色纷宇,僅存本色。 一 ...
    博土閱讀 203評論 0 1