摘要:并隱藏對象內(nèi)與用戶無關(guān)的數(shù)據(jù)結(jié)構(gòu)。有一種變化行為被稱為常量函數(shù),它們會返回一個硬編碼的值。盡管常量函數(shù)有其用途,但若與子類中只有常量函數(shù),實(shí)在沒有足夠的存在價(jià)值。你可以在超類中設(shè)計(jì)一個與常量函數(shù)返回值相應(yīng)的字段,從而完全除去這樣的子類。
前言
前面已經(jīng)對方法,類列舉了重構(gòu)方法?,F(xiàn)在該輪到字段了
注:值對象:不可變對象
引用對象:可變對象
你直接訪問一個字段,但與字段之間的耦合關(guān)系逐漸變得笨拙。
方法為這個字段建立取值/設(shè)值函數(shù),并且只以這些函數(shù)來訪問字段。(getter和setter方法)
動機(jī)子類可以通過覆寫一個函數(shù)而改變獲取數(shù)據(jù)的途徑;它還支持更靈活的數(shù)據(jù)管理方式,例如延遲初始化。
Replace Data Value with Object 對象取代數(shù)據(jù)值 問題你有一個數(shù)據(jù)項(xiàng),需要與其他數(shù)據(jù)和行為一起使用才有意義。
方法將數(shù)據(jù)項(xiàng)變成對象。
動機(jī)開發(fā)初期,一個用戶的信息只有名字,就用一個字符串來存,如果后期要添加用戶的信息。比如性別,年齡。會很難擴(kuò)展
Change value to Reference 將值對象改為引用對象 問題希望將多個相等對象,替換為一個對象。
方法使用單例模式。保證該對象只有一個
動機(jī)當(dāng)你希望在值對象中加一些可修改的字段時。保證所有對象都能被修改
Change Reference to Value 將引用對象改為值對象 問題你有一個引用對象,很小且不可變,而且不易管理。將它變成一個值對象。
注: 要在引用對象和值對象之間做選擇,有時并不容易。做出選擇后,你常會需要一條回頭路,
引用對象改為值對象
動機(jī)當(dāng)引用對象變得難以使用(比如因?yàn)橥絾栴})。就變回值對象
Replace Array with Object 以對象取代數(shù)組 問題你有一個數(shù)組,其中的元素各自代表不同的東西。以對象替換數(shù)組,對于數(shù)組中的每個元素,以一個字段來表示。方法
將每個元素用對象封裝
動機(jī)注:我覺得java程序員應(yīng)該很少這么用。一般都不會把不同的元素存到數(shù)組中。
Duplicate Observed data 復(fù)制被監(jiān)視數(shù)據(jù) 問題你有一些領(lǐng)域數(shù)據(jù)置身于GUI控件中,而領(lǐng)域函數(shù)需要訪問這些數(shù)據(jù)。
方法將該數(shù)據(jù)復(fù)制到一個領(lǐng)域?qū)ο笾?。建立一個觀察者模式,用以同步領(lǐng)域?qū)ο蠛虶UI對象內(nèi)的重復(fù)數(shù)據(jù)。
動機(jī)業(yè)務(wù)邏輯和用戶界面不能寫在一起,因?yàn)檫@樣用戶類就會有兩種職責(zé)。用戶類就變得很復(fù)雜。
Change Unidirection Association to Bidirectional 將單向關(guān)聯(lián)改為雙向關(guān)聯(lián)(特定情況使用) 問題兩個類都需要使用對方特性,但其間只有一條單向連接。
方法添加一個反向指針,并使修改函數(shù)能夠同時更新2條連接。
動機(jī)兩個類都需要使用對方特性,本重構(gòu)運(yùn)用反向指針實(shí)現(xiàn)雙向關(guān)聯(lián),其他技術(shù)需要其他重構(gòu)手法。
Change Bidirectional Association to Unidirection將雙向關(guān)聯(lián)改為單向關(guān)聯(lián)(特殊情況使用) 問題兩個類之間有雙向關(guān)聯(lián),但其中一個類如今不再需要另一個類的特性。
方法去除不必要的關(guān)聯(lián)。
動機(jī)雙向關(guān)聯(lián)很有用,但你必須為它付出代價(jià),那就是維護(hù)雙向連接、確保對象被正確創(chuàng)建和刪除而增加的復(fù)雜度。而且,由于很多程序員并不習(xí)慣使用雙向關(guān)聯(lián),它往往成為錯誤之源。
大量的雙向連接也很容易造成“僵尸對象”:某個對象本來應(yīng)該死亡了,卻仍然保留在系統(tǒng)中,因?yàn)閷λ囊脹]有完全清除。
此外,雙向關(guān)聯(lián)也迫使2個類之間有了依賴:對其中任一個類的任何修改,都可能引發(fā)另一個類的變化。如果這2個類位于不同的程序集,這種依賴就是程序集之間的相依。過多的跨程序集依賴會造就緊耦合的系統(tǒng),使得任何一點(diǎn)小小改動就可能造成許多無法預(yù)知的后果。
只有在真正需要雙向關(guān)聯(lián)的時候,才該使用它。如果發(fā)現(xiàn)雙向關(guān)聯(lián)不再有存在價(jià)值,就應(yīng)該去掉不必要的一條關(guān)聯(lián)。
你有一個字面數(shù)值,帶有特別含義。
方法創(chuàng)建一個常量,根據(jù)其意義為它命名,并將上述的字面數(shù)值替換為這個常量。
動機(jī)在計(jì)算科學(xué)中,魔法數(shù)是歷史悠久的不良現(xiàn)象之一。所謂魔法數(shù)是指擁有特殊意義,卻又不能明確表現(xiàn)出這種意義的數(shù)字。如果你需要在不同的地點(diǎn)引用同一個邏輯數(shù),魔法數(shù)會讓你煩惱不已,因?yàn)橐坏┻@些數(shù)發(fā)生變化,你就必須在程序中找到所有魔法數(shù),并將它們?nèi)啃薷囊槐椤>退隳悴恍枰薷?,要?zhǔn)確指出每個魔法數(shù)的用途,也會讓你頗費(fèi)腦筋。
Encapsulate Field 封裝字段 問題你的類中存在一個public字段。
方法將它聲明為private,并且提供相應(yīng)的訪問函數(shù)。
面向?qū)ο蟮氖滓瓌t之一就是封裝,或者稱為“數(shù)據(jù)隱藏”。按此原則,你絕不應(yīng)該將數(shù)據(jù)聲明為public,否則其他對象就有可能訪問甚至修改這項(xiàng)數(shù)據(jù),而擁有該數(shù)據(jù)的對象卻毫無察覺。于是,數(shù)據(jù)和行為就被分開了。
Encapsulate Collection 封裝集合 問題有一個函數(shù)返回一個集合。
方法讓這個函數(shù)返回該集合的一個只讀副本,并在這個類中提供添加/移除集合元素的函數(shù)。
動機(jī)我們常常會在一個類中使用集合來保存一組實(shí)例。這樣的類通常也會提供針對該集合的取值/設(shè)值函數(shù)。
但是,集合的處理方式應(yīng)該和其他種類的數(shù)據(jù)略有不同。取值函數(shù)不該返回集合自身,因?yàn)檫@會讓用戶得以修改集合內(nèi)容而集合擁有者卻一無所悉。也會對用戶暴露過多對象內(nèi)部數(shù)據(jù)結(jié)構(gòu)信息。如果一個取值函數(shù)確實(shí)需要返回多個值,它應(yīng)該避免用戶直接操作對象內(nèi)所保存的集合。并隱藏對象內(nèi)與用戶無關(guān)的數(shù)據(jù)結(jié)構(gòu)。
另外,不應(yīng)該為這整個集合提供設(shè)值函數(shù),但應(yīng)該提供用以為集合添加/移除元素的函數(shù)。這樣,集合擁有者就可以控制集合元素的添加和移除。
這條我還真沒懂
Replace Type Code with Class 以類來取代類型碼 問題類之中有一個數(shù)值類型碼,但它并不影響類的行為(不會因?yàn)樗母淖兌{(diào)用不同的邏輯)
方法以一個新的類替換該數(shù)值類型碼。
動機(jī)任何接受類型碼作為參數(shù)的函數(shù),所期望的實(shí)際上是一個數(shù)值,無法強(qiáng)制使用符號名。這會大大降低代碼的可讀性,從而成為bug之源。
Replace Type Code with Subclasses 以子類來取代類型碼 問題你有一個不可變的類型碼,它會影響類的行為。
方法以子類取代這個類型碼。
動機(jī)一般來說,這種情況的標(biāo)志就是像switch這樣的條件表達(dá)式。這種條件表達(dá)式可能有2種表現(xiàn)形式:switch語句或者if –then-else結(jié)構(gòu)。不論哪種形式,它們都是檢查類型碼值,并根據(jù)不同的值執(zhí)行不同的動作。這種情況下,你應(yīng)該以 Replace Conditional with Polymorphism (以多態(tài)取代條件表達(dá)式)進(jìn)行重構(gòu)。但為了那個順利進(jìn)行那樣的重構(gòu),首先應(yīng)該將類型碼替換為可擁有多態(tài)行為的繼承體系。這樣一個繼承體系應(yīng)該以類型碼宿主類為基類,并針對每一種類型碼建立一個子類。
Replace Type Code with State/Strategy 以狀態(tài)/策略取代類型碼 問題你有一個類型碼,它會影響類的行為,但你無法提供繼承手法消除它。
方法以狀態(tài)對象取代類型碼。
本項(xiàng)重構(gòu)和Replace Type Code with Subclass (以子類取代類型碼)類似,但如果“類型碼在對象生命期中發(fā)生變化”或“其他原因使得宿主類不能被繼承”,你也可以使用本重構(gòu)。本重構(gòu)使用State模式和Strategy模式。
State模式和Strategy模式非常相似,因此無論你選擇其中哪一個,重構(gòu)過程都是一樣的。“選擇哪個模式”并非問題的關(guān)鍵所在,你只需要選擇更合適特定情境的模式就行了。如果你打算在完成本重構(gòu)后再以Replace Conditional with Polymorphism (以多態(tài)取代條件表達(dá)式)簡化一個算法,那么選擇Strategy模式較合適;如果你打算搬移狀態(tài)相關(guān)的數(shù)據(jù),而且你把新建對象視為一種變遷狀態(tài),就應(yīng)該選擇State模式。Replace Subclass with Fieldls 以字段取代子類 問題
你的各個子類的唯一差別只在“返回常量數(shù)據(jù)”的函數(shù)身上。
方法修改這些函數(shù),使它們返回超類中的某個(新增)只讀,然后銷毀子類。
動機(jī)建立子類的目的,是為了增加新特性或變化其行為。有一種變化行為被稱為“常量函數(shù)”,它們會返回一個硬編碼的值。這東西有其用途:你可以讓不同的子類中的同一個訪問函數(shù)返回不同的值。你可以在超類中將訪問函數(shù)聲明為抽象函數(shù),并在不同子類中讓它返回不同的值。
盡管常量函數(shù)有其用途,但若與子類中只有常量函數(shù),實(shí)在沒有足夠的存在價(jià)值。你可以在超類中設(shè)計(jì)一個與常量函數(shù)返回值相應(yīng)的字段,從而完全除去這樣的子類。如此一來就可以避免因繼承而帶來的額外復(fù)雜性。
注:這好像和以子類取代狀態(tài)碼有一定沖突
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/69736.html
摘要:函數(shù)重構(gòu)重構(gòu)有很大一部分都是在重構(gòu)函數(shù)。這條也要具體情況具體使用函數(shù)對象取代函數(shù)函數(shù)對象代替函數(shù)大函數(shù)變成類你有一個大型函數(shù),其中對局部變量的使用使你無法采用提煉函數(shù)。將這個大型函數(shù)放進(jìn)一個單獨(dú)對象中,如此一來局部變量就成了對象內(nèi)的字段。 函數(shù)重構(gòu) 重構(gòu)有很大一部分都是在重構(gòu)函數(shù)。尤其是長函數(shù)。這是問題的根源。以下是重構(gòu)方法 Extract Method 提煉函數(shù) 提煉函數(shù):(由復(fù)雜的...
摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡介領(lǐng)域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號作者架構(gòu)師奮斗者掃描主頁左側(cè)二維碼,加入群聊,一起學(xué)習(xí)一起進(jìn)步歡迎點(diǎn)贊收藏留言前情提要無意間聽到領(lǐng)導(dǎo)們的談話,現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨(dú)立帶隊(duì)的人太少,簡而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...
摘要:重構(gòu)在不改變代碼的外在的行為的前提下對代碼進(jìn)行修改最大限度的減少錯誤的幾率本質(zhì)上,就是代碼寫好之后修改它的設(shè)計(jì)。重構(gòu)可以深入理解代碼并且?guī)椭业?。同時重構(gòu)可以減少引入的機(jī)率,方便日后擴(kuò)展。平行繼承目的在于消除類之間的重復(fù)代碼。 重構(gòu) (refactoring) 在不改變代碼的外在的行為的前提下 對代碼進(jìn)行修改最大限度的減少錯誤的幾率 本質(zhì)上, 就是代碼寫好之后 修改它的設(shè)計(jì)。 1,書中...
摘要:為何重構(gòu)重構(gòu)有四大好處重構(gòu)改進(jìn)軟件設(shè)計(jì)如果沒有重構(gòu),程序的設(shè)計(jì)會逐漸腐敗變質(zhì)。經(jīng)常性的重構(gòu)可以幫助維持自己該有的形態(tài)。你有一個大型函數(shù),其中對局部變量的使用使你無法采用。將這個函數(shù)放進(jìn)一個單獨(dú)對象中,如此一來局部變量就成了對象內(nèi)的字段。 哪有什么天生如此,只是我們天天堅(jiān)持。 -Zhiyuan 國慶抽出時間來閱讀這本從師傅那里借來的書,聽說還是程序員的必讀書籍。 關(guān)于書的高清下載連...
閱讀 2959·2023-04-26 02:22
閱讀 2309·2021-11-17 09:33
閱讀 3177·2021-09-22 16:06
閱讀 1107·2021-09-22 15:54
閱讀 3555·2019-08-29 13:44
閱讀 1950·2019-08-29 12:37
閱讀 1342·2019-08-26 14:04
閱讀 1940·2019-08-26 11:57