面向對象原則之一 開放封閉原則(開閉原則)


前言

面向對象有人分為五大原則,分別為單一職責原則、開放封閉原則、依賴倒置原則、接口隔離原則、里氏替換原則。

也有人分為六大原則,分別為單一職責原則、開放封閉原則、依賴倒置原則、接口隔離原則、里氏替換原則、迪米特法則。

 

現在我們來介紹開放封閉原則,也叫開閉原則

 

開閉原則

1)概念

官方說法是 軟件實體(模塊、類、函數等)應該可以擴展,但是不可以修改。也就是說軟件對擴展開放,對修改關閉。

需要說明的是,對修改關閉不是說軟件設計不能做修改,只是盡量不要做不必要的修改。怎么才能做到呢?那就是有相應的擴展性。

其實,軟件有相應的擴展性是好處,但是不能說每個地方都有擴展。反而造成了代碼的臃腫。所以這里的擴展與修改關閉是有限制的。

開閉原則,可以說是其他五大原則的實現,也是面向對象設計的終極目標。我們也可以說成開閉原則是其他原則的核心。

說了這些概念性的東西,似懂非懂。我們可以試試從下面的例子來看看是否更加上心。

2)深入理解

開閉原則怎么能更深入的理解呢?還是說說我們身邊的例子吧。

比如我們平常喝水用的一次性紙杯。平常人只是用來裝水。喝完水就扔了。這就是這個紙杯的生命周期。紙杯這一生只完成了它的一個功能:裝水。紙杯此時就很封閉了,沒有什么擴展性。

此時,我看到身邊有一支花苗,我想要拿回家種。但是沒有容器呀? 啊?旁邊不是有一個紙杯嗎,可以用此紙杯來種這朵花苗。

紙杯有了它的另外一個擴展性,就是種花苗。

紙杯不僅有裝水、種花苗的用途,以后還可以有裝小垃圾、沖茶、回收等功能。對於以后這些功能,我們要想到他們的擴張性。

在紙杯只有一個裝水的功能的時候,我們只寫一個紙杯功能類,說紙杯能裝水。但是以后有擴展呢?這一方面我們要預先判斷。預先判斷它以后可能會根據需求的變動而擴展。對於紙杯本來的裝水功能,不能說不能修改,此功能只能在此函數、類中修改。這就是開閉原則的核心。

所以,紙杯在開閉原則所體現的是:盡量少修改,未來可能擴展的模塊、類做好預算的判斷。如果要修改,只能在此函數此類修改,不能牽涉到其他地方。

下面,我們用UML類圖來直觀地說明一下紙杯的設計吧。

當紙杯只有一個功能,裝水時。有一個紙杯操作接口,有一個紙杯操作實現類。

image

當我們要添加一個功能 種花苗時,我們不也是加一個方法嗎?如下:

image

當添加N個方法時,不也是在紙杯的操作接口上面添加N個方法嗎?

我們想一想,此時已經背離了我們的開閉原則。因為每添加一個方法,都要在操作類上面做修改。所以,我們按照開閉原則,開做了以下合理的設計:

image

從上面可以看出,我們把紙杯的操作類,統一寫成一個接口,每個不同的操作繼承此接口來完成各自操作。我們還開到多了一個類,叫客戶端類,其實此類也不難理解。也就是要最終操作紙杯的類。

 

3)其他例子

開閉原則其實在大話設計模式中說得非常好,讓人通俗易懂。

它舉了一個例子,我覺得說得非常好。是加減乘除法的例子。

開始需求是做一個加法的操作。后來繼續加入減法、乘法、除法。

開始我們想加法以后可能會做一個需求變更:加入其它的算法法則。所以我們要有一個預判性,這個預判性會導致我們項目以后的擴展性,也會導致如果需求發生變更,程序修改的難易程度。

所以,我們要做一個算法法則的操作類,加減乘除法都繼承此操作接口。再加一個算法法則的客戶端類類操作此算法。

我們來上一下大話設計模式中的圖:

image

 

4)總結

開閉原則是我們面向對象設計的目標,我們靈活地運用好此目標也不是易事。所以開閉原則要深入的理解,才能做好面向對象的編程,才能做一個好的軟件。

 

其他鏈接:

開放封閉原則(開閉原則)

單一職責原則

依賴倒置原則

接口隔離原則

里氏替換原則

迪米特法則

 

此文轉發,請注明出處,謝謝。

 

 

可以關注本人的公眾號,多年經驗的原創文章共享給大家。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM