天天看點

OCP開放封閉原則

一、定義

  軟體實體(類、子產品、函數等)應該是可以擴充的,但是不可修改。

  如果正确的應用了OCP原則,那麼 以後在進行同樣的改動時,就隻需要添加新的代碼,不必修改已經正常運作的代碼。

二、OCP概述

  1.對于擴充是開放的

  這意味着子產品的行為是可以擴充的。當應用的需求改變時,我們可以對子產品進行擴充,使其具有滿足那些改變的新行為。換句話說,我們可以改變子產品的功能。

  2.對于修改是封閉的

  對子產品進行擴充時,不必改動子產品的源代碼或者二進制代碼。

  3.有何問題

  這兩個特征好像是互相沖突的。擴充子產品行為的通常方式就是修改該子產品的源代碼。不允許修改子產品常常都認為具有固定的行為。

  4.如何實作?(抽象)

  怎麼可能在不改動源代碼的情況下去更改它的行為呢?如果不更改一個子產品,又怎麼能夠去改變它的功能呢?

  答案是抽象。在C#中,可以建立出固定卻能夠描述一組任意個可能行為的抽象體。這個抽象體就是抽象基類。而這一組任意個可能的行為則表現為可能的派生類。

  子產品可能對抽象體進行操作。由于子產品依賴于一個固定的抽象體,是以它對于更改可以是封閉的。同時,通過從這個抽象體派生,可以擴充此子產品的行為。

  下圖展示了一個簡單的不遵循OCP的設計。Client類和Server類都是具體類。Client類使用Server類,如果我們希望Client對象使用另一個不同的伺服器對象,那麼就必須要把Client類中使用Server類的地方更改為新的伺服器類。

  

OCP開放封閉原則

 

  下圖則使用Strategy模式(政策模式)展示了一個針對上述問題的遵循OCP的設計。

OCP開放封閉原則

  下圖展示了另一個使用Template method模式(模版方法模式)的結構。

OCP開放封閉原則

  和圖2中Client類的函數類似,Policy類具有一組實作了某個政策的具體公共函數。和前面一樣,這些政策函數根據一些抽象接口描繪了要完成的功能,不同的是,在這個結構中,這些抽象接口是Policy類本身的一部分。在C#中,它們是抽象方法。這些函數在Policy類子類型中實作。這樣,可以通過從policy類派生出新類的方式,對Policy中指定的行為進行擴充。

三、結論

  在很多方面,OCP都是面向對象設計的核心所在。遵循這個原則可以帶來面向對象技術所聲稱的巨大好處:靈活性、可重用性以及可維護性。

  拒絕不成熟的抽象和抽象本身一樣重要。

繼續閱讀