前言
在物件導向設計過程中,「決定把責任放在那兒」即使不是最重要的事,也是最重要的事之一。
這個思想其實對類較重要,在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...