天天看點

寫給自己看的小設計1 - 面向對象設計總綱

張無忌與設計模式有關系麼?讓我來侃一下。

  今天與人閑扯中無意之間提到了倚天屠龍記中的張無忌,這是一個普通的帶點軟弱的主角,性格複雜。回來後細細思索一番,我竟然覺得他的學藝之路竟然是頗有啟發性,想來金庸大師也是哲學方面的高才啊。下面來回憶一下張教主的成才之路,看我是否有值得借鑒之處。

面向對象思想 - 任督二脈

  打通任督二脈,這是修習高等國術的必經步驟,這個大家看過武俠的都知道,也基本都見識過了(一般都要借助外力,比如武功高強的師傅,能力超凡的道具等等)。道理也很簡單,如果任督二脈不通,真氣流轉不流暢的,這個當然就不能發揮自己體内最大的能量了。

  基本上,任何用過面向對象語言(Java, C++, C#等)的同學們張口就能說出面向對象的三大特征:繼承(運作機制),封裝(手段),多态(表征變化)。但是有幾個人曾經試圖深層次的了解過這6個字背後的含義?面向對象思想是軟體工程發展史上的偉大裡程碑。它提供了軟體設計與開發的新思路:那就是一切皆是對象。這種思想展現了人們對于世界的重新認識。這種認識展現到實際的行動中,就是使用對象去表述世界發展的一切活動。為了生動描述事物之間特性的傳承性,“繼承”就誕生了,每門面向對象的語言都是使用繼承機制實作了大部分代碼的複用。為了描述事物之間相同特性基礎上表現出來的差異性,于是“多态”就被創造出來。為了描述事物的完整性和相對封閉性,“封裝”就提上了日程,細節從此不需要再去關注。這是面向對象世界觀的3大根本特征,也是面向對象設計的核心根基,隻有深刻了解了他們,你的神功才會一日千裡。

面向對象設計原則 - 九陽神功

  當你做到任何時候,任何場合,眼中隻有對象的時候,恭喜你任督二脈已經打通,你可以學習任何一門高深的内功了。為什麼先學習内功,這個大家也都熟悉。沒有内功的配合,任何高深的招式都是浮雲。是以要天下無敵,必須要練就一身深厚的内功,比如九陽神功。

  對象的三大特征全部都是用了,表明在你眼中一切都應該是對象,你已經是面向對象了,但是并不是說這就是好的面向對象了。如何要評判一個系統是好的面向對象呢?一般就是參照如下“SOLID”标準:

單一職責原則(SRP):做一個專一的人

  隻并且隻做好一件事,這一條原則其實不僅僅适用于對象,也同樣适用于函數,變量等一切程式設計元素。當然在商業模式中,将一件事做到極緻就是成功,我個人覺得這一條也還是成立的。

開放封閉原則(OCP):改造世界大部分不是破壞原來的秩序

  在對象世界中,添加新的功能一般意味着新的對象,一個好的設計也意味着這個新的修改不要大幅度波及現有的對象。這一條了解起來最簡單,實施起來卻是最困難。無數的模式和解耦方法都是為了達到這個目的而誕生的。

裡氏替換原則(LSP):長大後,我就成了你

  父類使用的地方,子類也可以使用。這一條希望子類不要破壞父類的接口成員。一旦破壞了,就如果人與人之間破壞合同一樣,有時候會很糟糕。

接口分離原則(ISP):不要一口吃成胖子

  接口不要過于龐大,繁雜的東西是難于了解,難于擴充,難于修改的。這一條的目的與單一職責原則類似,不過是更加強調了接口的邏輯一緻性和簡易性。

依賴倒置原則(DIP):抽象的藝術才有生命力

  高層與底層元件之間都應該依賴于抽象的元件。這一條深刻揭示了抽象的生命力,抽象的對象才是最有表達能力的對象,因為它通常是“無形”的,可以随時填充相關的細節。

  除了這幾個基本的設計原則,還有一些衍生的原則,掌握它們,你将更好的面向對象。

迪米特法則:盡量不與無關的類發生關系。

  不要讓類也染上人們之間的那種神秘的暧昧關系。對象之間聯系越是簡單,則越是容易管理。

好萊塢法則:不要調用我,讓我調用你。

  電影中常說,單線聯系最安全,如此是也。

多使用組合,少使用繼承

  複用的手段除了繼承這種強限制手段,組合這種弱耦合的關系更加靈活。

實作依賴于抽象

  這一點一般也稱為面向接口程式設計,保證了對象之間關系穩定。

模式 - 乾坤大挪移

  當張無忌學會了九陽神功以後,大家發現了沒,居然最普通的毛賊都打不過,都要靠他們打他來反擊。這樣談何天下無敵呢。不過當他學會了乾坤大挪移以後,那真的是如同鳳凰涅槃,瞬間變成了超級賽亞人。這個道理似乎也很簡單,光有高深的内功,但是沒有運轉自如,充分發揮内功的招式,同樣也是不成的。招式那可是前輩們經驗的總結,是精華啊。學會了這個,你才有決勝天下的資本。

  世間原本沒有模式,使用的人多了,就有模式了。模式是經驗的總結,是“巨俠”們的心血。大型模式如架構模式(分層,MVC,PAC,黑闆,中間人,反射,管道,微核,REST架構等),它們描述了系統大骨架的建構過程;中等規模的模式如設計模式(GOF 23種模式,POSA中的各種設計模式),它們描述了子系統中元件的建構過程;小的模式如各種語言中的程式設計實踐(C#中的IDispose模式,C++中的Counted Point模式等),它們描述了解決語言中特定問題的實施方案;這些模式合起來就是面向對象程式設計過程中針對特定問題的乾坤大挪移神功。

重構 - 太極拳

  練習太極拳是需要超凡的悟性的,太極拳重在以意運轉,不能有絲毫外在強加的限制,這一點看過原著的同學們都很清楚。從太極拳問世後,人們才重新的體會了什麼叫以柔克剛!

  重構是精心打磨代碼的過程,是任何資深碼農的必備技能。重構不是無目的的,重構是一種不改變代碼行為的前提下,改善代碼可讀性,可擴充性的過程。

  之是以需要重構,就是因為代碼也是符合事物發展規律的,也有一個從出生到成長,從強壯到衰敗,從衰敗到腐爛的過程,而且是逐漸的,不知不覺的就從好變爛了。毫無疑問,并不是所有的爛代碼都是一次寫成的,也許最初的代碼設計的是很好的,但是一旦被多個人修改過以後,就變壞了,我想這個大家肯定是深有體會的。代碼總是在所有人的共同“努力”下寫爛的。

  如果說上面的那些技術都有迹可循,規則性比較強的話,相對來說,重構的技術要相對柔和一點,沒有那麼強烈的限制條款,而且雖然也有像介紹“代碼壞味道”的偉大著作(重構一書)誕生,但是通常的人腦海中對于重構的沖動,根本沒有像使用模式那麼強烈,根本不會想到重構會是那麼的重要,就如同書中的那些高人們根本不會想到如此緩慢而且無固定招式的太極拳會是那麼強悍一樣。重構與太極拳一樣,都是真正的“意識流”。

抽象與組合 - 獨孤九劍

  要說金庸小說中最厲害的武功,那不是乾坤大挪移,也不是太極拳,更不是葵花寶典,而是獨孤九劍。那是神馬境界啊?九劍破遍天下任何拳腳,氣功,暗器,十八般兵器啊。這個才叫“無敵”。當然了,這個武功不是随便是誰都能練得成的,也就是像令狐大哥那樣智慧超群,灑脫一場,具備一定内功(後期更輔助以吸星大法),武功又雜的小哥才能練;而且這個練習過程也非常長,據風老介紹,令狐老兄刻苦練習數十年後才能與東方不敗一戰。

  我們再看看該神功原創者獨孤大俠一輩子兵器的變遷:從利劍到重劍,到木劍,再到無劍。大家發現了沒,到了最後抛開一切的招式,内功,融彙貫通,水乳交融以後,才是超凡入聖,這個時候也才發現原來一切又回到了起點:原來武功就是這麼簡單,就是鍛煉與發揮人體的最大能量,随便的一揮一灑就有無與倫比的威力。返璞歸真這才是武者的終極,青銅門後面的永恒(出自盜墓筆記一書)。

  不管是面向過程,還是面向對象,不管是面向元件,還是面向服務,歸根結底隻不過是人們對世界的抽象方式和抽象的粒度不同而已,把抽象出來的東東組合起來,形成一定的規範和流程,依靠這些去解決實際的問題,這就是程式設計。抽象與組合,才是終極的藝術。

繼續閱讀