設計模式之開篇原則(一)

設計模式到底是什麼?它是對整個軟件系統的拆分,組裝,並決定模塊間關係以及如何互動的方式。究其本質,設計模式就是以封裝、繼承、多態、抽象的語言特性爲基礎,以六大設計原則的靈魂組合而總結出的一系列優化方案。本篇文章主要講的是設計模式之六大基本原則:單一職責、開閉原則、裏式替換、依賴倒置、接口隔離、迪力米特里原則

單一職責

我們知道功能完備的軟件系統是複雜的,系統的拆分與模塊化是不可或缺的,而面向對象是以類來劃分模塊邊界的,也就是說每個類都代表着一個功能角色模塊,其職責應該是單一的,不是自己分內的事不應該負責,這就是單一職責原則。

舉個例子,燈泡一定是可以亮和滅的,我們定義一個燈泡類並且包含“功率屬性”以及“通電”和“斷電”兩個功能方法,這便是對燈泡的封裝,一對大括號“{}”定義了其類模塊的邊界。

雖然說我的領域我做主,但絕不可肆意妄爲。比如現在客戶要求這個燈泡可以閃爍的霓虹燈效果,我們該怎樣實現?直接在電燈類裏再封裝一堆邏輯電路控制其閃爍,比如新加一個flash()方法,並不停來回調用通電斷電?這顯然是錯誤的,燈泡就是燈泡,它只能亮和滅,能不能閃爍不是燈泡的職責,既然進行分類,就不要不倫不類。所以我們需要把閃爍控制電路獨立出來,它們之間的通信應該通過接口去調用,劃清界限,各司其職,這纔是類封裝的意義。

單一職責原則規定,對任何類的修改只能有一個原因。例如我們的燈泡類,它的職責就是照明,與其無關的一切修改動機都不予考慮。所以說燈泡絕不能封裝與其本身職責不相干的功能,這樣就保證其職責的單一性原則,類與類之間有明確的職責劃分。

開閉原則

開閉原則,其中“開”指的是對擴展是開放的,”閉“則指的是對修改是關閉。通俗來講就是不要修改已有的代碼,而是去寫新的代碼。這對於已經上線並穩定運行的軟件項目來說更爲重要,修改代碼的代價是巨大的,小小一個修改有可能會造成整個系統癱瘓,因爲其可能會波及到的地方變得不可預知,難以估量。

舉個簡單的例子,我們有一個筆類用來畫畫,它有一個很簡單的draw方法。這時業務擴展,需要畫各種顏色的畫,難道我們繼續修改這個筆類的draw方法去接受顏色參數並加入大量邏輯判斷嗎?如果後期又需要水彩、水墨、油畫等等顏料效果就需要沒完沒了的對筆進行代碼修改,大量的邏輯代碼會堆積在這個類中,就像拆開封裝的機器殼子對內部電路二次修改,各種導線焊點雜亂無章、臃腫不堪。

造成這種局面肯定是系統設計上的問題,我們要對其重新審視,對筆類進行抽象,定義好一個繪畫行爲draw(),但具體怎樣畫不應予以關心。如此便建立了軟件體系的高層抽象,如果後期要進行擴展,那麼去添加新類並繼承我們的高層抽象即可,各種筆保證了各自的特性,你畫你的,我畫我的。所以說開閉原則是通過抽象去實現的,高層的泛化保證了底層實現的多態化擴展

里氏替換

此原則指出是任何父類出現的地方子類一定也可以出現,換個角度講也就是說一個優秀的設計中有引用父類的地方,一定可以用子類進行替換。其實面向對象設計語言的特性”繼承與多態“正是爲此而生,而我們在設計的時候一定要考慮到這一點,寫框架代碼的時候要面向抽象編程,而不是深入到具體子類中去,這樣才能保證子類多態的可能性。

假設我們定義有這麼一個類“禽類”,給它加一個飛翔方法fly(),於是客戶端可以自由自在地調用其飛翔方法。不巧某天需要鴕鳥加入禽類的行列,可惜地是鴕鳥並不會飛,這下就鬧得整個雞飛狗跳,此時客戶端就不能調用禽類的飛翔方法了,因爲這個禽類有可能就是鴕鳥,這就違反了里氏替換原則。我們意識到最初的設計一定是有問題的,因爲不是所有“禽類”都會“飛”,所以對於禽類不該有飛翔方法。

我們這裏提供一種思路做重構,把禽類的飛翔方法抽離出去給一個接口Flyable,這樣鴕鳥依舊可以繼承禽類,對於其他可以飛的鳥則是繼承禽類並實現Flyable接口。這樣一來,客戶端如果用的是禽類,那一定是鳥而絕不是獸,但不一定能飛,比如是鴕鳥或者火雞;而如果用的是Flyable那它就必然能飛,也許是蝙蝠(獸類)甚至可以是飛機,這些子類一定是在其基類定義範圍內可以隨意替換而不引起任何系統問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章