[設計模式] 開放封閉原則

開發封閉原則(Open-Closed Principle OCP)編程

Software entities(classes,modules,functions etc) should open for extension ,but close for modification.設計模式

   什麼意思呢?spa

   所謂開放封閉原則就是軟件實體應該對擴展開發,而對修改封閉。開放封閉原則是全部面向對象原則的核心。軟件設計自己所追求的目標就是封裝變化,下降耦合,而開放封閉原則正是對這一目標的最直接體現。設計

   開放封閉原則主要體如今兩個方面:code

   對擴展開放,意味着有新的需求或變化時,能夠對現有代碼進行擴展,以適應新的狀況。對象

   對修改封閉,意味着類一旦設計完成,就能夠獨立其工做,而不要對類盡任何修改。繼承

 

爲何要用到開放封閉原則呢?接口

軟件需求老是變化的,世界上沒有一個軟件的是不變的,所以對軟件設計人員來講,必須在不須要對原有系統進行修改的狀況下,實現靈活的系統擴展。ip

 

如何作到對擴展開放,對修改封閉呢?ci

      實現開放封閉的核心思想就是對抽象編程,而不對具體編程,由於抽象相對穩定。讓類依賴於固定的抽象,因此對修改就是封閉的;而經過面向對象的繼承和多態機制,能夠實現對抽象體的繼承,經過覆寫其方法來改變固有行爲,實現新的擴展方法,因此對於擴展就是開放的。

      對於違反這一原則的類,必須經過重構來進行改善。經常使用於實現的設計模式主要有Template Method模式和Strategy 模式。而封裝變化,是實現這一原則的重要手段,將常常變化的狀態封裝爲一個類。

以銀行業務員爲例

沒有實現OCP的設計:

01 public class BankProcess
02
03     {  //存款
04
05        public void Deposite(){}
06
07         //取款
08
09         public void Withdraw(){ }
10
11         //轉帳
12
13         public void Transfer(){}
14
15     }
16
17     public class BankStaff
18
19     {
20
21         private BankProcess bankpro = new BankProcess();
22
23         public void BankHandle(Client client)
24
25         {
26
27             switch (client.Type)
28
29             {  //存款
30
31                 case "deposite":
32
33                     bankpro.Deposite();
34
35                     break;
36
37                     //取款
38
39                 case "withdraw":
40
41                     bankpro.Withdraw();
42
43                     break;
44
45                     //轉帳
46
47                 case "transfer":
48
49                     bankpro.Transfer();
50
51                     break;
52
53             }
54
55         }
56
57     }

     這種設計顯然是存在問題的,目前設計中就只有存款,取款和轉帳三個功能,未來若是業務增長了,好比增長申購基金功能,理財功能等,就必需要修改BankProcess業務類。咱們分析上述設計就不能發現把不能業務封裝在一個類裏面,違反單一職責原則,而有新的需求發生,必須修改現有代碼則違反了開放封閉原則。

      從開放封閉的角度來分析,在銀行系統中最可能擴展的就是業務功能的增長或變動。對業務流程應該做爲擴展的部分來實現。當有新的功能時,不須要再對現有業務進行從新梳理,而後再對系統作大的修改。

如何才能實現耦合度和靈活性兼得呢?

那就是抽象,將業務功能抽象爲接口,當業務員依賴於固定的抽象時,對修改就是封閉的,而經過繼承和多態繼承,從抽象體中擴展出新的實現,就是對擴展的開放。

如下是符合OCP的設計:

首先聲明一個業務處理接口

01 public  interface IBankProcess{  void Process();}
02
03 public class DepositProcess : IBankProcess
04
05     {
06
07         public void Process()
08
09         //辦理存款業務
10
11             Console.WriteLine("Process Deposit");
12
13         }
14
15 }
16
17 public class WithDrawProcess : IBankProcess
18
19     {
20
21         public void Process()
22
23         //辦理取款業務
24
25             Console.WriteLine("Process WithDraw");
26
27         }
28
29 }
30
31 public class TransferProcess : IBankProcess
32
33     {
34
35         public void Process()
36
37         //辦理轉帳業務
38
39             Console.WriteLine("Process Transfer");
40
41         }
42
43     }
44
45 public class BankStaff
46
47     {
48
49         private IBankProcess bankpro = null;
50
51         public void BankHandle(Client client)
52
53         {
54
55             switch (client.Type)
56
57             {   //存款
58
59                 case "Deposit":
60
61                     userProc = new DepositUser();
62
63                     break;
64
65                     //轉帳
66
67                 case "Transfer":
68
69                     userProc = new TransferUser();
70
71                     break;
72
73                     //取款
74
75                 case "WithDraw":
76
77                     userProc = new WithDrawUser();
78
79                     break;
80
81             }
82
83             userProc.Process();
84
85         }
86
87     }

 

這樣當業務變動時,只須要修改對應的業務實現類就能夠,其餘不相干的業務就沒必要修改。當業務增長,只須要增長業務的實現就能夠了。

 

設計建議:

開放封閉原則,是最爲重要的設計原則,Liskov替換原則和合成/聚合複用原則爲開放封閉原則提供保證。

能夠經過Template Method模式和Strategy模式進行重構,實現對修改封閉,對擴展開放的設計思路。

封裝變化,是實現開放封閉原則的重要手段,對於常常發生變化的狀態,通常將其封裝爲一個抽象,例如銀行業務中IBankProcess接口。

拒絕濫用抽象,只將常常變化的部分進行抽象。

相關文章
相關標籤/搜索