面向對象五大原則-----開放封閉原則

  什麼是開放封閉原則

  開放封閉原則(OCP,Open Closed Principle)是全部面向對象原則的核心。軟件設計自己所追求的目標就是封裝變化、下降耦合,而開放封閉原則正是對這一目標的最直接體現。其餘的設計原則,不少時候是爲實現這一目標服務的,例如以Liskov替換原則實現最佳的、正確的繼承層次,就能保證不會違反開放封閉原則。 編程

  關於開放封閉原則,其核心的思想是:軟件實體應該是可擴展,而不可修改的。也就是說,一個軟件實體應當對擴展是開放的,而對修改是封閉的。 設計模式

  所以,開放封閉原則主要體如今兩個方面:對擴展開放,意味着有新的需求或變化時,能夠對現有代碼進行擴展,以適應新的狀況。對修改封閉,意味着類一旦設計完成,就能夠獨立完成其工做,而不要對類進行任何修改。架構

  在設計一個模塊時,應當使得這個模塊能夠在不被修改的前提下被擴展。也就是說,應當能夠在沒必要修改源代碼的狀況下修改這個模塊的行爲。學習

  設計的目的便在於面對需求的改變而保持系統的相對穩定,從而使得系統能夠很容易的從一個版本升級到另外一個版本。spa

  「需求老是變化」、「世界上沒有一個軟件是不變的」,這些言論是對軟件需求最經典的表白。從中透射出一個關鍵的意思就是,對於軟件設計者來講,必須在不須要對原有的系統進行修改的狀況下,實現靈活的系統擴展。而如何能作到這一點呢?設計

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

實施開放封閉原則的基本思路,同時這種機制是創建在兩個基本的設計原則的基礎上,這就是Liskov替換原則和合成/聚合複用原則。對象

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

  怎樣作到開放封閉原則

  實際上,絕對封閉的系統是不存在的。不管模塊是怎麼封閉,到最後,總仍是有一些沒法封閉的變化。而咱們的思路就是:既然不能作到徹底封閉,那咱們就應該對那些變化封閉,那些變化隔離作出選擇。咱們作出選擇,而後將那些沒法封閉的變化抽象出來,進行隔離,容許擴展,儘量的減小系統的開發。當系統變化來臨時,咱們要及時的作出反應。繼承

      咱們並不懼怕改變的到來。當變化到來時,咱們首先須要作的不是修改代碼,而是儘量的將變化抽象出來進行隔離,而後進行擴展。面對需求的變化,對程序的修改應該是儘量經過添加代碼來實現,而不是經過修改代碼來實現。

      實際上,變化或者可能的變化來的越早,抽象就越容易,相對的,代碼的維護也就越容易;而當項目接近於完成而來的需求變化,則會使抽象變得很困難——這個困難,並非抽象自己的困難,抽象自己並無困難,困難在於系統的架構已經完成,修改牽扯的方面太多而使得抽象工做變得很困難。

  咱們舉個銀行業務的例子

  銀行有四項業務,存款,取款,轉帳和買基金

  若是用普通的方式來寫

 1 /*
 2  * 銀行業務員
 3  */
 4 public class BankWorker {
 5     //負責存款業務
 6     public void saving() {
 7         System.out.println("進行存款操做");
 8     }
 9     
10     //負責取款業務
11     public void drawing() {
12         System.out.println("進行取款操做");
13     }
14     
15     //負責轉帳
16     public void zhuanzhang() {
17         System.out.println("進行轉帳操做");
18     }
19     
20     //負責基金的申購
21     public void jijin() {
22         System.out.println("進行基金申購操做");
23     }
24 }

  這樣等同於一個業務員負責了全部的業務,站在銀行窗口焦急等待的用戶,在長長的隊伍面前顯得無奈。因此,將這種無奈遷怒到銀行的頭上是理所固然的,由於銀行業務的管理顯然有不當之處。銀行的業務人員面對蜂擁而至的客戶需求,在排隊等待的人們並不是只有一種需求,有人存款、有人轉帳,

也有人申購基金,繁忙的業務員來回在不一樣的需求中穿梭,手忙腳亂的尋找各類處理單據,電腦系統的功能模塊也在不一樣的需求要求下來回切換,這就是一個發生在銀行窗口內外的無奈場景。而我每次面對統一排隊的叫號系統時,都爲前面長長的等待人羣而叫苦,從梳理銀行業務員的職責來看,在管理上

他們負責的業務過於繁多,將其對應爲軟件設計來實現,這種拙劣的設計就上面例子中的方式。

  這樣,若是要修改的話,若是銀行新添加了一項業務,這個業務員就得新增這項業務,這樣擴展行就不好,並且,只要新增業務就要修改源碼。

  因此下面咱們用符合開放封閉原則的方式來編寫代碼

  把不一樣的業務分配給不一樣的業務員,因此先編寫抽象業務員父類

1 /*
2  * 銀行業務員接口,是全部銀行業務員的抽象父類
3  */
4 public interface BankWorker {
5     public void operation();
6 }

   而後,在編寫各個負責各個業務的業務員

 1 /*
 2  * 負責存款業務的業務員
 3  */
 4 public class SavingBankWorker implements BankWorker {
 5 
 6     public void operation() {
 7         System.out.println("進行存款操做");
 8     }
 9     
10 }
 1 /*
 2  * 負責取款業務的業務員
 3  */
 4 public class WithdrawalsBankWorker  implements BankWorker{
 5 
 6     public void operation() {
 7         System.out.println("進行取款操做");
 8     }
 9     
10 }
 1 /*
 2  * 負責轉帳業務的業務員
 3  */
 4 public class ZhuanZhangBankWorker implements BankWorker {
 5 
 6     public void operation() {
 7         System.out.println("進行轉帳操做");
 8     }
 9 
10 }
 1 /*
 2  * 負責基金業務的業務員
 3  */
 4 public class JiJinBankWorker implements BankWorker {
 5 
 6     public void operation() {
 7         System.out.println("進行基金申購操做");
 8     }
 9 
10 }

  能夠看到,這樣的形式就能夠作到,增長業務只需新增業務員便可,沒必要對原有業務進行任何的修改,也符合了開放封閉原則 

  開放封閉原則的優越性

  1.經過擴展已有的軟件系統,能夠提供新的行爲,以知足對軟件的新需求,是變化中的軟件有必定的適應性和靈活性。

  2.已有的軟件模塊,特別是最重要的抽象模塊不能再修改,這就使變化中的軟件系統有必定的穩定性和延續性。

   使用建議

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

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

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

  四、拒絕濫用抽象,只將常常變化的部分進行抽象,這種經驗能夠從設計模式的學習與應用中得到。

相關文章
相關標籤/搜索