軟件實體(類、模塊、函數等)應該是能夠擴展的,可是不可修改。服務器
若是正確的應用了OCP原則,那麼 之後在進行一樣的改動時,就只須要添加新的代碼,沒必要修改已經正常運行的代碼。函數
1.對於擴展是開放的設計
這意味着模塊的行爲是能夠擴展的。當應用的需求改變時,咱們能夠對模塊進行擴展,使其具備知足那些改變的新行爲。換句話說,咱們能夠改變模塊的功能。對象
2.對於修改是封閉的blog
對模塊進行擴展時,沒必要改動模塊的源代碼或者二進制代碼。接口
3.有何問題擴展
這兩個特徵好像是互相矛盾的。擴展模塊行爲的一般方式就是修改該模塊的源代碼。不容許修改模塊經常都認爲具備固定的行爲。軟件
4.如何實現?(抽象)二進制
怎麼可能在不改動源代碼的狀況下去更改它的行爲呢?若是不更改一個模塊,又怎麼可以去改變它的功能呢?方法
答案是抽象。在C#中,能夠建立出固定卻可以描述一組任意個可能行爲的抽象體。這個抽象體就是抽象基類。而這一組任意個可能的行爲則表現爲可能的派生類。
模塊可能對抽象體進行操做。因爲模塊依賴於一個固定的抽象體,因此它對於更改能夠是封閉的。同時,經過從這個抽象體派生,能夠擴展此模塊的行爲。
下圖展現了一個簡單的不遵循OCP的設計。Client類和Server類都是具體類。Client類使用Server類,若是咱們但願Client對象使用另外一個不一樣的服務器對象,那麼就必需要把Client類中使用Server類的地方更改成新的服務器類。
下圖則使用Strategy模式(策略模式)展現了一個針對上述問題的遵循OCP的設計。
下圖展現了另外一個使用Template method模式(模版方法模式)的結構。
和圖2中Client類的函數相似,Policy類具備一組實現了某個策略的具體公共函數。和前面同樣,這些策略函數根據一些抽象接口描繪了要完成的功能,不一樣的是,在這個結構中,這些抽象接口是Policy類自己的一部分。在C#中,它們是抽象方法。這些函數在Policy類子類型中實現。這樣,能夠經過從policy類派生出新類的方式,對Policy中指定的行爲進行擴展。
在不少方面,OCP都是面向對象設計的核心所在。遵循這個原則能夠帶來面向對象技術所聲稱的巨大好處:靈活性、可重用性以及可維護性。
拒毫不成熟的抽象和抽象自己同樣重要。