面向对象设计原则之开闭原则
兩截門--一個被水平分割為兩部分的門,這樣每一部分都可以獨立保持開放或封閉
開放-封閉原則(The Open-Closed Principle)
軟件實體(類、模塊、函數)應該是可以擴展的,但是不可以修改的。
如果程序中的一處改動就會產生連鎖反應,導致一系列的相關模塊的改動,那么設計就具有僵化的臭味。如果正確的應用OCP,那么以后再進行同樣的改動時,就只需要添加新的代碼,而不必改動已經正常運行的代碼。
描述
主要兩個特征:
模塊的行為是可以擴展的,當應用的需求改變時,我們可以對模塊進行擴展,使其具有滿足那些改變的新行為。簡言之,我們可以改變模塊的功能。
對模塊進行擴展時,不必改動模塊的源代碼。
關鍵是抽象
下圖展示了一個簡單的不遵循OCP的設計。Client類和Server類都是具體類,Client類使用Server類。如果我們希望Client對象使用另外一個不同的服務器對象,那么就必須要把Client類中使用Server類的地方更改為新的服務器類
下圖是根據OCP設計重構的設計
ClientInterface類是一個擁有抽象成員函數的抽象類,Client類使用這個抽象類。如果我們希望Client對象使用一個不同的服務器類,那么只需要沖ClientInterface類派生一個新的類,無需對Client類做任何改動。
Shape應用程序
應用程序中有Circle、Square列表,需求是:繪制他們
從OCP原則考慮,設計方案如下,
根據此設計,如果新增一個Triangle類,只需新增代碼即可,無需改動上述代碼,達到了開閉原則。真的嗎???
并非100%封閉
如果需求要求所有圓必須在正方形之前繪制,那么DrawAllShape無法對這種變化做到封閉。要實現這個需求,我們需要修改DrawAllShape,使它首先掃描列表中的圓,然后在掃描所有的正方形。預測變化和貼切的結構
一般來說,無論模塊是多么封閉,都會存在一些無法對之封閉的變化,沒有對于所有的情況都貼切的模型。 既然不能完全封閉,就要有策略的對待這個問題,設計人員必須對于他設計的模塊應該對哪種變化封閉作出選擇,他必須先猜測出最有可能發生的變化種類,然后構造抽象來隔離那些變化。這需要設計人員具備一些從經驗中獲得的預測能力。 遵循OCP的代價是昂貴的,創建正確的抽象是要花費開發時間和精力的,同時,那些抽象也增加了軟件設計的復雜性,開發人員有能力處理的抽象的數量也是有限的,顯然,我們希望把OCP的應用限定在可能會發生的變化上。- 只受一次愚弄
最初編寫代碼的時候,假設變化不會發生,當變化發生了,我們就創建抽象來隔離以后發生的同類變化。 - 刺激變化
盡早查明可能發生的變化,盡早接受變化帶來的改變。
Shape改造
class Shape{draw();//precedes();precedes(OrderRule order){} } Class DrawAllShape{sort(list);void drawAllShapes(List<Shape> lists){for(Shape shape :lists){shape.draw();}} }precedes()考慮到枚舉排序的話違背了OCP,可以將規則定義起來,改造成precedes(OrderRule order),排序規則從OrderRule中讀取,此時對與Shape繪制順序的變化不封閉的唯一部分就是OrderRule。
結論
在許多方面,OCP都是面向對象設計的核心所在。遵循這個原則可以的帶來面向對象技術所聲稱的巨大好處(靈活性,可重用性,可維護性)。對于應用程序中的每個部分都肆意的進行抽象同樣不是一個好主意。正確的做法是,開發人員應該僅僅對程序中呈現出頻繁變化的那些部分做出抽象。拒絕不成熟的抽象和抽象本身一樣重要。轉載于:https://www.cnblogs.com/vincent0928/p/6568354.html
總結
以上是生活随笔為你收集整理的面向对象设计原则之开闭原则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SqlServerDBCC SHRINK
- 下一篇: 如何修改容器的一些参数