明天就是五一了,先祝各位老友們五一快樂。
      公司終于讓我做設(shè)計(jì)了,哈哈,不過是詳細(xì)設(shè)計(jì),還沒有到系統(tǒng)的份上。不還我還是比較滿意的,以前有辭職的想法,現(xiàn)在,怎么也要等這個(gè)項(xiàng)目做完之后再說了。
      這段時(shí)間一直在研究“面向?qū)ο笤O(shè)計(jì)的原則”,以下是學(xué)習(xí)的一點(diǎn)經(jīng)驗(yàn):
      1.類的設(shè)計(jì)原則
         在網(wǎng)上,一般認(rèn)為燈的設(shè)計(jì)原則有五類,如下:
   1)SRP,單一職責(zé)原則,一個(gè)類應(yīng)該有且只有一個(gè)改變的理由。 
                  所謂單一職責(zé)原則,就是就一個(gè)類而言,應(yīng)該僅有一個(gè)引起它的變化的原因。換句話說,一個(gè)類的功能要單一,只做與它相關(guān)的事情。
  這個(gè)原則是最簡(jiǎn)單、最容易理解,卻是最不容易做到的事情。這個(gè)原則的道理誰都理解,可是在實(shí)踐中呢?

  我們來看一個(gè)例子:

if(action.equals("load")&&tab.equals("1")){
request.setAttribute("tabId",tab);
form.set("tabId",tab);
speciManager.loadIncrement(actionForm, request, tab);
}
if(action.equals("Save")&&tab.equals("1")){
System.out.println("inter increment save action");
……
request.setAttribute("tabId",tab);
}
if(action.equals("load")&&tab.equals("2")){
request.setAttribute("tabId",tab);
form.set("tabId",tab);
speciManager.loadMeasureMent(actionForm, request, tab);
}
if(action.equals("Save")&&tab.equals("2")){
……
System.out.println("inter increment save action");
speciManager.loadIncrement(actionForm, request, tab);
form.set("tabId",tab);
request.setAttribute("tabId",tab);

}
  一看就知道這個(gè)類做了太多的工作,它既要load一個(gè)tab為1的頁面和一個(gè)tab為2的頁面;又要save一個(gè)tab為1頁面和一個(gè)tab為2的頁面。這個(gè)類的代碼我只截取了里面很少的一部分,絕大部分的代碼我都省略掉了。這段代碼寫到最后是越來越混亂,直到最后失敗。

  對(duì)照著這個(gè)例子,我們?cè)賮矸治鲆幌聻槭裁匆袷貑我宦氊?zé)愿則:

  第一、有助于我們分析和編碼的思路的清晰。當(dāng)你的代碼里有了三層或以上的if語句或for語句的嵌套的時(shí)候,你不要跟我說,你已經(jīng)把問題分析得很清楚了。多層嵌套的if或for語句只能說明你還沒有把問題分析清楚。

  第二、使我們的編碼、測(cè)試和維護(hù)變得簡(jiǎn)單。

  第三、將一個(gè)個(gè)復(fù)雜的問題簡(jiǎn)單化以后,易于代碼的重用。當(dāng)你的代碼的多個(gè)功能攪和在一起的時(shí)候,你是沒辦法考慮代碼的重用的,因?yàn)槟愕拿恳惶幋a都有不同。

  第四、易于系統(tǒng)的擴(kuò)展。 
 2)OCP,開放封閉原則,你應(yīng)該能夠不用修改原有類就能擴(kuò)展一個(gè)類的行為。 
               “開一閉”原則講的是:一個(gè)軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。 這個(gè)規(guī)則說的是,在設(shè)計(jì)一個(gè)模塊的時(shí)候,應(yīng)當(dāng)使這個(gè)模塊可以在不被修改的前提下被擴(kuò)展。 從另外一個(gè)角度講,就是所謂的“對(duì)可變性封裝原則”。“對(duì)可變性封裝原則”意味著兩點(diǎn): 1 .一種可變性不應(yīng)當(dāng)散落在代碼的很多角落里,而應(yīng)當(dāng)被封裝到一個(gè)對(duì)象里面。同一種可變性的不同表象意味著同一個(gè)繼承等級(jí)結(jié)構(gòu)中的具體子類。 2.一種可變性不應(yīng)當(dāng)與另一種可變性混合在一起。即類圖的繼承結(jié)構(gòu)一般不應(yīng)超過兩層。 做到“開—閉”原則不是一件容易的事,但是也有很多規(guī)律可循,這些規(guī)律同樣也是設(shè)計(jì)原則,它們是實(shí)現(xiàn)開—閉原則的工具
  3)  LSP,Liskov替換原則,派生類要與其基類自相容。 
                   里氏代換原則:就是子類代替父類,程序或者代碼的行為不變。例如如果對(duì)每一個(gè)類型為T1的對(duì)象o1,都有類型為T2的對(duì)象o2,使得以T1定義的所有程序P在所有對(duì)象o1都換成o2時(shí),程序P的行為沒有變化,那么類型T2是T1的子類型。 即如果一個(gè)軟件實(shí)體使用的是基類的話那么也一定適用于子類。但反過來的代換不成立。 如果有兩個(gè)具體類A和B之間的關(guān)系違反了里氏代換原則,可以在以下兩種重構(gòu)方案中選擇一種: 1 創(chuàng)建一個(gè)新的抽象類C,作為兩個(gè)具體類的超類,將A和B共同的行為移動(dòng)到C中,從而解決A和B行為不完全一致的問題。 2 從B到A的繼承關(guān)系改寫為委派關(guān)系。 
 4) DIP,依賴倒置原則,依賴于抽象而不是實(shí)現(xiàn)。 
                  依賴倒轉(zhuǎn)原則講的是:要依賴于抽象,不要依賴于具體。即針對(duì)接口編程,不要針對(duì)實(shí)現(xiàn)編程。針對(duì)接口編程的意思是,應(yīng)當(dāng)使用接口和抽象類進(jìn)行變量的類型聲明、參量的類型聲明,方法的返還類型聲明,以及數(shù)據(jù)類型的轉(zhuǎn)換等。不要針對(duì)實(shí)現(xiàn)編程的意思就是說,不應(yīng)當(dāng)使用具體類進(jìn)行變量的類型聲明、參量的類型聲明,方法的返還類型聲明,以及數(shù)據(jù)類型的轉(zhuǎn)換等。 依賴倒轉(zhuǎn)原則雖然強(qiáng)大,但卻不易實(shí)現(xiàn),因?yàn)橐蕾嚨罐D(zhuǎn)的緣故,對(duì)象的創(chuàng)建很可能要使用對(duì)象工廠,以避免對(duì)具體類的直接引用,此原則的使用還會(huì)導(dǎo)致大量的類。維護(hù)這樣的系統(tǒng)需要較好的面向?qū)ο蟮脑O(shè)計(jì)知識(shí)。 此外,依賴倒轉(zhuǎn)原則假定所有的具體類都是變化的,這也不總是正確的。有一些具體類可能是相當(dāng)穩(wěn)定、不會(huì)發(fā)生變化的,消費(fèi)這個(gè)具體類實(shí)例的客戶端完全可以依賴于這個(gè)具體類。
  5) ISP,接口隔離原則,客戶只要關(guān)注它們所需的接口。 
                  接口隔離原則講的是:使用多個(gè)專門的接口比使用單一的接口要好。從客戶的角度來說:一個(gè)類對(duì)另外一個(gè)類的依賴性應(yīng)當(dāng)是建立在最小的接口上的。如果客戶端只需要某一些方法的話,那么就應(yīng)當(dāng)向客戶端提供這些需要的方法,而不要提供不需要的方法。提供接口意味著向客戶端作出承諾,過多的承諾會(huì)給系統(tǒng)的維護(hù)造成不必要的負(fù)擔(dān)。 

         2.包原則

      REP,重用發(fā)布等價(jià)原則,重用的粒度就是發(fā)布的粒度。 
      CCP,共同封閉原則,包中的所有類對(duì)于同一類性質(zhì)的變化應(yīng)該是共同封閉的。  
      CRP,共同重用原則,一個(gè)包中的所有類應(yīng)該是共同重用的。 

      3  .包之間的耦合性原則 
       ADP,無環(huán)依賴原則,在包的依賴關(guān)系圖中不允許存在環(huán)。 
      SDP,穩(wěn)定依賴原則,朝著穩(wěn)定的方向進(jìn)行依賴。 
      SAP,穩(wěn)定抽象原則,包的抽象程度應(yīng)該和其穩(wěn)定程度一致。