重構筆記03 物件之間搬遷特性

2021-09-22 13:07:37 字數 4546 閱讀 3367

前言

在物件導向設計過程中,「決定把責任放在那兒」即使不是最重要的事,也是最重要的事之一。

這個思想其實對類較重要,在js中,函式應該完成什麼職責,也需要分清楚,不要函式做了自己的事情,又做了一部分其它函式的事情。

在js中,往往只有乙個類,物件導向的思想其實比較難,沒有一定功力不能很好的運用,我也在學習

很多js中其實就只有乙個類,乙個外掛程式就是乙個類,而且這個類還是假的,繼承、封裝神馬的要理解還是不容易的,所以路還長!

搬遷函式

我們的程式中如果有個函式與其所駐類的另乙個類有更多的交流(呼叫後者、或者被後者呼叫)

那麼在該函式最常引用的類中建立乙個有著類似行為的新函式,將久函式變成乙個單純的委託函式,或者移除舊函式

搬遷函式是重構理論的支柱,如果乙個類有太多行為,或者乙個類與另乙個類有太多合作而成高度耦合,我們就需要搬遷函式

ps:其實在單頁應用中,mvc的結構很可能導致這種情況發現,後面點我們搞點**出來看看

我們的程式中會有這樣的函式,使用另乙個物件次數比使用自己的次數還多,搬遷時這就是函式歸屬的重要依據

來乙個例子吧,這裡利用乙個表示「賬戶」的account類來說明

1 var accounttype = function () {};

2 accounttype.prototype =

4 };

5 var account = function () ;

9 account.prototype = else

18     },

19     bankcharge: function ()

24 };

在這個程式中,加入有幾種新賬戶,每一種都有自己的「透支金額計費規則」,所以overdraftcharge可能需要搬遷到accounttype中去

如何做首先,我們要觀察overdraftcharge使用的每一項特性,考慮那些特性是否可與他一起搬遷

這個程式中,_dayoverdrawn會被留下,因為這個值會隨不同賬號變化而變化,於是調整後的**如下:

1 var accounttype = function () {};

2 accounttype.prototype = ,

4     overdraftcharge: function (account) else

12     }

13 };

14 var account = function () ;

18 account.prototype =

24 };

這裡也可以將daysoverdrawn作為引數傳入,但是如果後面會傳入多個字段,就要改**,所以直接傳入物件吧

搬移字段

搬移欄位在再js程式中可能用得會多一點,在我們的程式中,某個欄位被自己類之外的類多次使用的話

那麼,在目標類新建乙個字段,修改源字段的所有使用者,讓他們使用新字段

為什麼這麼幹?

在類之間移動狀態和行為,是重構過程中必不可少的措施,隨著系統發展,我們會發現,自己需要新的類,並需要將現有工作責任移動新類中

但是這個星期看似合理正確的設計決策,下個星期可能就錯了的情況也不是沒有

如果我們發現,乙個欄位被其它類過多使用,那麼我們就該拋棄他了 範例

繼續我們上面的例子吧

1 var account = function () ;

5 account.prototype =

9 };

我們現在想把表示利率的_interestrate搬移到accounttype類去,目前已經有幾個函式引用他了,interestforamount_days是其中之一

所以我們現在accounttype中建立_interestrate欄位與相應函式,以下是重構後的**

1 var accounttype = function () ;

4 accounttype.prototype =

8 };

9 var account = function () ;

12 account.prototype =

16 };

提煉類某個類做了應該兩個類做的事,那麼就新建乙個類,將相關的字段和函式移過去

ps:我們從開始到現在就了解了,重構的一大手段就是消除臨時變數,另乙個方法就是職責分離了

我們經常聽到這句話,乙個類應該是乙個清除的抽象,處理一些明確的責任,但在實際工作中,類會不斷擴張

我們會在這加一些功能,然後在那加一些資料,給某個類新增一項新任務時,你會覺得不值得為這項責任分離出乙個單獨的類

於是責任不斷增加,這個類最後就會越來越複雜,很快這個類就連自己也不想讀了

這樣的類往往有大量的函式和資料,所以不好理解,這個時候我們需要考慮應該分離哪部分,並將它們寫到乙個單獨的類中

如果這些資料和某些函式總是一起出現,某些資料經常同時變化,那麼就分離吧

ps:說了這麼多還是虛的,來一段**吧

1 var person = function () ;

6 person.prototype = ,

8     gettel: function () ,

11     getofficeareacode: function () ,

14     setofficeareacode: function (arg) ,

17     getofficenumber: function () ,

20     setofficenumber: function (arg)

23 };

1 var tel = function () ;

5 tel.prototype = ,

9     setareacode: function (arg) ,

12     getnumber: function () ,

15     setnumber: function (arg)

18 };

19 var person = function () ;

23 person.prototype = ,

25     gettel: function ()

28 };

想想,person當然不只tel這點屬性,tel也可能會有其它動作,如果寫在一起,後面**膨脹是可以預見的

將類內聯化

如果某個類沒做什麼事情,那麼將類消除吧,將他完成的特性移動到另乙個類中,這個方法與提煉類完全相反

範例就是將上面的**寫回去......

隱藏委託關係

客戶通過乙個委託來呼叫另乙個物件,在伺服器上建立客戶的所有函式,用以隱藏委託關係

「封裝」即使不是物件最關鍵的特徵,也是最關鍵的特徵之一

封裝意味著每個物件都應該盡可能少了解系統其它部分,如此一來,其它地方變化了,就管我屁事了(變化比較容易進行) 範例

本例中,出了人以為,多了乙個部門的類啦:

1 var department = function (manager) ;

5 department.prototype =

9 };

10 var person = function () ;

13 person.prototype =

17 };

如果客戶想知道某人的經理是誰,他必須先取得department物件

manager = p.getdepartment().getmanager()

這樣有乙個問題就是,對使用者揭露了department的工作原理,於是客戶指定通過department可以追蹤經理資訊,如果可以隱藏department的話,就可以減少耦合

這裡就來乙個委託:

1 var department = function (manager) ;

5 department.prototype =

9 };

10 var person = function () ;

13 person.prototype = ,

17     getmanager: function ()

20 };

這樣的話,使用者就不知道有department這個東西了

移除中間人

某個類做了過多的簡單委託動作,那麼就讓使用者之間呼叫委託類吧

這個與上面的是反著的,各位對照著看吧

引入外加函式

我們有時需要為提供服務的類增加乙個函式,但我們無法修改這個類,那麼在客戶類中建立乙個函式,並以第一引數形式傳入乙個伺服器類例項

1 var d = new date(previousend.getyear(), previousend.getmonth(), previousend.getday() + 1); 2 

3 var d = nextday(previousend);

4 function nextday(arg)

這種事情發生的很多,我們正在使用乙個類,他提供了很多服務,但是我們突然需要乙個新類,這個類卻無法提供,那麼我們可能會咒罵,完了修改原始碼

如果原始碼不能修改,我們就得在客戶端補齊函式啦

引入本地擴充套件

你需要為服務類提供一些額外函式,但你無法修改這個類,建立乙個新類,使他包含這些額外的函式,讓這個擴充套件成為源類的子類或者包裝類

這個與上面類似,小的要看神都龍王去了,所以暫時到這吧......

重構 在物件之間搬移特性

1 move method 搬移函式 有個函式與所在類之外的另乙個類進行更多的交流 呼叫或被呼叫 在該函式最常引用的類中建立乙個有著類似行為的新函式。將舊函式變為乙個單純的委託函式,或者將舊函式刪除。2 move field 搬移字段 某個欄位被其所屬類之外的另乙個類頻繁呼叫。3 extract c...

重構 在物件之間搬移特性

你的程式中,有個函式與其所駐類之外的另乙個類進行更多交流 呼叫後者,或被後者呼叫 則在該函式最常引用的類中建立乙個有著類似行為的新函式,將舊函式變成乙個單純的委託函式,或是將舊函式完全移除。動機 如果乙個類有太多行為,或如果乙個類與另乙個類有太多合作而形成高度耦合,就使用搬移函式,通過這種手段,可以...

重構之在物件之間搬移特性

1.move method 搬移函式 你的程式中,有個函式與其所駐 class 之外的另乙個 class 2.move field 搬移值域 在 target class 建立乙個 new field 修改source field 的所有使用者,令它們改用 new field。3.extract c...