前言
■本書是一本程式集?並不是。
■本書是一本程式設計故事匯?並不是。
本書是一本透過故事說明程式如何設計的程式設計方法集。
■本書是給連 Hello World 都沒寫過的非程式設計師看的書嗎?並不是。
■本書是給玩過穿孔紙帶(0/1)、寫過組合語言、BASIC、C、C++、Java、C#、Python 等語言,開發過大型系統的骨灰級程式設計師看的書嗎?並不是。
本書希望能給這樣的讀者一些好的建議和提示:
■渴望了解 OO(Object Oriented,物件導向)世界的初學者
■困惑於僵硬、脆弱、無法重複使用的程式設計師
■打著 OO 程式設計的旗號,做著 PO(Procedure Oriented,過程)開發導向的基於物件的程式設計師
■習慣了用 Python 框架、函數庫、自動化開發而忽視了軟體開發本質的程式設計師
■決心脫離「藍領程式設計師」圈的程式設計師
✤ 本書起因
寫這本書源於我的一次做教育訓練的經歷,學生大多是電腦專業學生或有過一定經驗的在職開發者。他們都知道類別、方法、建構方法、甚至抽象類別、介面等概念,並用Visual Studio 寫過桌面或Web 程式,可是當我提問為什麼要物件導向,它的好處在哪裡時,卻沒有人能完整地講出來,多數人的反應是,概念是知道的,就是表達不清楚。
針對於此,我舉了中國古代的四大發明中活字印刷的例子(見第1 章),透過一個虛構的曹操做詩的情景,把物件導向的幾大好處講解了一下,學生普遍感覺這樣的教學比直接告訴物件導向有什麼好處要更加容易理解和記憶。
這就使得我不斷地思考這樣一個問題,學一門技術是否需要趣味性以及通俗性的引導。
我在思考中發現,看小說時,一般情況下我都可以完整地讀完它,而閱讀技術方面的圖書,卻很少按部就班、每章每頁的仔細閱讀。儘管這兩者有很大區別,技術書中可能有不少知識是已經學會或暫時用不上的內容,但也不得不承認,小說之所以可以堅持讀完是因為我對它感興趣,作者的精妙文筆版面配置在吸引我。而有些技術書的枯燥乏味使得讀者閱讀很難堅持,很多時候讀個幾章就進入書架了。
技術的教學同樣如此,除非學生是抱著極大的學習動機來參與其中,否則照本宣科的教學、枯燥乏味的講解,學生一定會被龐雜的概念和複雜的邏輯攪暈了頭腦,致使效果大打折扣。也正因如此,造成部分學生學了四年的電腦程式設計,卻可能連物件導向有什麼好處都還說不清。
為什麼不可以讓技術書帶點趣味性呢,哪怕這些趣味性與所講的技術並不十分貼切,只要不是影響技術核心的本質,不產生重大的錯誤,讓讀者能輕鬆閱讀它,並且有了一定的了解和感悟,這要比一本寫得高深無比卻被長期束之高閣的書要好得多。
也正是這個原因,本人開始了關於設計模式的趣味性寫作的嘗試。
✤ 本書讀者
顯然本書不是給零程式設計經驗的人看的,對想入這一行的朋友來說,找一門程式語言,從頭開始或許才是正道。而本書也不太適合有多年物件導向開發經驗、對常用設計模式瞭若指掌的人—畢竟這裡更多的是講解一些基本觀念的東西。
我時常拿程式設計師的成長與足球運動員的成長做對比。
GoF 的《設計模式》好比是世界頂級足球射門集錦,《重構》、《敏捷軟體開發》、《設計模式解析》好比是一場場精彩的足球比賽。雖然我為之瘋狂,為之著迷,可是我並不只是想做一個球迷(軟體使用者),而是更希望自己能成為一個球員(軟體設計師),能夠親自上場比賽,並且最終成為球星(軟體架構師)。我仔細地閱讀這些被譽為經典的著作,認真實踐其中的程式,但是我總是半途而廢、堅持不下去,我痛恨自己意志力的薄弱、憎惡自己輕易地放棄,難道我真的就是那麼的笨?
痛定思痛,我終於發現,比利、馬拉度納不管老、胖都是用來敬仰的,貝克漢、小羅納多不管美、醜都是用來欣賞的,但他們的球技……唉,客氣地說,是不容易學會的,客觀地說,是不可能學得會的。為什麼會這樣?原來,我學習中缺了一個很重要的環節,我們在看到了精彩的球賽、欣賞球星高超球技的同時,卻忽略了球星的成長過程。他們儘管有一定天分,但卻也是從最底層透過努力一點一點慢慢顯露出來的,我們需要的不僅是世界盃上的那定乾坤的一腳,更需要了解這一腳之前是如何練出那種神奇腳法的方法,對於程式設計師來講,精彩的程式的實現想法,要比看到精彩的程式更加令人期待。
本書顯然不是培養球星(軟體架構師)的豪門俱樂部,而是訓練足球基本功的體校,教育訓練的是初學足球的小球員(物件導向的程式設計師),本書希望的是讀者閱讀後可以打好物件導向的基礎,從而更加容易並深入理解和感受GoF 的《設計模式》以及其他大師作品的魅力。
✤ 本書定位
本書是在學習許多大師智慧結晶的圖書作品、分享了多位朋友的實踐經驗的基礎上,加之自己的程式設計感受寫出來的。正如牛頓有句名言:
「如果說我比別人看得更遠些,那是因為我站在了巨人的肩上。」
顯然本書並沒有創造或發現什麼模式,因此談不上站在巨人肩膀上而看得更遠。所以作者更希望本書能成為一些準備攀登物件導向程式設計高峰的朋友的登山引路人、提攜者,在您登山途中迷路時給予指引一條可以堅實踩踏的路線,在您峭壁攀岩不慎跌落時給予保護和鼓勵。
✤ 本書特色
本書有兩個特色。
第一個特色是重視過程。我看了太多的電腦程式設計類的圖書,大多數書籍都是在集中講授優秀的解決方案或完美的程式範例,但對這些解決方案和程式的演變過程卻不夠重視。好書之所以好,就是因為作者可以站在學習者的角度去講解問題所在,讓學習門檻降低。《重構與模式》中有一句經典之語:「如果想成為一名更優秀的軟體設計師,了解優秀軟體設計的演變過程比學習優秀設計本身更有價值,因為設計的演變過程中蘊藏著大智慧。」本人就希望能透過小菜與大鳥的對話,在不斷地提問與回答過程中,在程式的不斷重構演變中,把設計模式的學習門檻降低,讓初學者可以更加容易地理解,為什麼這樣設計才好,你是如何想到這樣設計的。
第二個特色就是貼近生活。儘管程式設計是嚴謹的,不容大話和戲說,但生活卻是多姿多彩的,而設計模式也不是完全孤立於現實世界而憑空想出來的理論。事實上所有的模式都可以在生活中找到對應。因此,透過主人翁小菜和大鳥的對話,將求職、面試、工作、交友、投資、兼職、辦公室文化、生活百味等等非常接近程式設計師生活原貌的場景寫到了書中,用一個個小故事來引出模式,會讓讀者相對輕鬆地進入學習設計模式的狀態。當然,此舉的最大目的還是為了深入淺出,而非純粹噱頭。
✤ 本書內容
本書通篇都是以情景對話的形式,用一個又一個的小故事或程式設計範例來組織的。全書共分為四個部分。
■第一部分(第 0 章)是楔子,主要是向不熟悉物件導向程式設計的讀者一個觀念說明,並透過一個例子的演變介紹類別、封裝、繼承、多形、介面、集合等概念。
■第二部分(第 4~5 章,第 11 章)是物件導向的意義和好處以及幾個重要的設計原則—透過小菜面試的失敗引出;
■第三部分(第 1~3 章、第 6~10 章、第 12~28 章)是詳細講解 23 個設計模式;
■第四部分(第 29 章)是對設計模式的複習,利用小菜夢到的超級模式大賽的場景,把所有的物件導向和模式概念都擬人化來趣味性地複習設計模式之間的異同和關鍵點;
✤ 本書人物及背景
小菜:原名蔡遙,22 歲,上海人,上海某大學電腦專業大學四年級學生,成績一般,考研剛結束,即將畢業,正求職找工作,夢想進大廠。大鳥:原名李大遼,29 歲,小菜的表哥,雲南昆明人,畢業後長期從事軟體開發和管理工作,近期到上海發展,借住小菜家在寶山的空房內。小菜以向大鳥學習為由,也從市區父母家搬到寶山與大鳥同住。
✤ 本書研讀方法
本書建議按順序閱讀,如果您感覺由於物件導向知識的匱乏(例如對繼承、多形、介面、抽象類別的理解不足)造成閱讀上的困難,不妨先閱讀楔子的「教育訓練實習生—物件導向基礎」部分,然後再從第1 章開始閱讀。如果您已經對不少設計模式很熟悉,也不妨挑選不熟悉的模式章節閱讀。
本書中的很多精華都來自許多大師作品,建議讀者透過筆記形式記錄,將會有助您的記憶和理解設計模式,增強最終的讀書效果。
✤ 關於本書學習的疑問解答
■看本書需要什麼基礎?
主要是Java 或其他程式語言的基礎知識,如變數、分支判斷、迴圈、函數等程式設計基礎,關於物件導向基礎可參看本書的楔子(第0章)。
■設計模式是否有必要全部學一遍?
答案是,Yes !別被那些說什麼設計模式大多用不上,根本不用全學的輿論所左右。儘管現在設計模式遠遠不止23 種,對所有都有研究是不太容易的,但就像作者本人一樣,在學習GoF 複習的23 個設計模式過程中,你會被那些程式設計大師們進行偉大的技術思想洗禮,不斷增加自己對物件導向的深入理解,從而更好的把這種思想發揚光大。這就如同高中時學立體幾何感覺沒用,但當你裝潢好房子購買家俱時才知道,有空間感,懂得空間計算是如何的重要,你完全可能遇到買了一個大號的冰箱卻放不進廚房,或買了開關門的衣櫥(移門不佔空間)卻因床在旁邊堵住了門而打不開的尷尬。
重要的不是你將來會不會用到這些模式,而是透過這些模式讓你找到「封裝變化」、「物件間鬆散耦合」、「針對介面程式設計」的感覺,從而設計出易維護、易擴充、易重複使用、靈活性好的程式。成為詩人後可能不需要刻意地按照某種模式去創作,但成為詩人前他們一定是認真地研究過成百上千的唐詩宋詞、古今名句。
如果說,數學是思維的體操,那設計模式,就是物件導向程式設計思維的體操。
■我學了設計模式後時常會過度設計,怎麼辦?
作者建議,暫時現象,繼續努力。
設計模式有四境界:
1. 沒學前是一點不懂,根本想不到用設計模式,設計的程式很糟糕;
2. 學了幾個模式後,很開心,於是到處想著要用自己學過的模式,於是時常造成誤用模式而不自知;
3. 學完全部模式時,感覺諸多模式極其相似,無法分清模式之間的差異,有困惑,但深知誤用之害,應用之時有所猶豫;
4. 靈活應用模式,甚至不應用具體的某種模式也能設計出非常優秀的程式,以達到無劍勝有劍的境界。
從作者本人的觀點來說,不會用設計模式的人要遠遠超過過度使用設計模式的人,從這個角度講,因為怕過度設計而不用設計模式顯然是因噎廢食。當你意識到自己有過度使用模式的時候,那就證明你已意識到問題的存在,只有透過不斷的鑽研和努力,你才能突破「不識廬山真面目,只緣身在此山中」的瓶頸,達到「會當凌絕頂,一覽眾山小」的境界。
✤ 程式語言的差異
本書講的是物件導向設計模式,是用Java 語言撰寫,但本書並不是主要講解Java 語言的圖書,因此本書同樣適合C#、VB.NET、C++ 等其他一些物件導向語言的讀者閱讀來學習設計模式。
就C# 而言,主要差異來自C# 對於子類別繼承父類別或實現介面用的都是":",而Java 中兩者是有區別的。
當Cat 繼承抽象類別Animal 時,C# 語法是public class Cat : Animal
當Superman 實現介面IFly 時,C# 語法是public class Superman : IFly
然後C# 中類別中的方法,如果父類別是虛方法,需要子類別指定new 或是override 修飾符號。還有一些其他差異,但基本都不影響本書的閱讀。
C++ 的程式設計師,可能在語言上會有些差異,不過本書應該不會因為語言造成對物件導向思想的誤讀。
✤ 本書程式下載
儘管本書中的程式都提供下載,但不經過讀者的自己手動輸入過程,其實閱讀的效果是大打折扣的。強烈建議讀者根據範例自己寫程式,只有在運行出錯,達不到預期效果時再查看本書提供的來源程式,這樣或許才是最好的學習方法。有問題可即時與我聯繫。部落格是cj723.cnblogs.com/。
✤ 不是一個人在戰鬥
首先要感謝我的妻子李秀芳對我寫作本書期間的全力支持,沒有她的理解和鼓勵,就不可能有本書的出版。父母的養育才有作者本人的今天,本書的出版,尋根溯源,也是父母用心教育的結果。養育之恩,沒齒難忘。
本書起源於本人在「博客園」網站的部落格cj723.cnblogs.com/ 中的連載文章《小菜程式設計成長記》。沒想到連載引起了不小的反響,網友普遍認為本人的這種技術寫作方式新穎、有趣、喜歡看。正是因為許多網友的支持,本人有了要把GoF 的23 種設計模式全部故事化的衝動。
非常感謝這些在部落格回覆中鼓勵我的朋友。
這裡需要特別提及洪立人先生,他是本人在寫書期間共同為理想奮鬥的戰友,寫作也獲得了他的大力支持和幫助。在此對他表示衷心的感謝。
寫作過程中,本人參考了許多國內外大師的設計模式的著作。尤其是《設計模式》( 作者: 簡稱GoF 的Erich Gamma,Richard Helm,RalphJohnson,John Vlissides)、《設計模式解析》( 作者:Alan Shalloway,James R. Trott)、《敏捷軟體開發:原則、模式與實踐》(作者:RobertC.Martin)、《重構—改善既有程式的設計》(作者:Martin Fowler)、
《重構與模式》(作者:Joshua Kerievsky)、《Java 與模式》(作者:閻宏)等等,沒有他們的貢獻,就沒有本書的出版。也希望本書能成為更好閱讀他們這些大師作品的前期讀物。
寫作過程中, 本人還參考了www.dofactory.com/ 關於23 個設計模式的講解,並引用了他們的結構圖和基本程式。在部落格園中的許多朋友, 比如張逸、呂震宇、李會軍、idior、Allen Lee 的博文,MSDNSmartCast 中李建忠的講座,CSDN 部落格中的大衛、ai92 的博文,網站J 道www.jdon.com 的版主banq 的文章都給本人的寫作提供了非常大的指引和幫助,在此表示感謝。另外部落格園的雙魚座先生還對本人的部分程式提出了整改意見,也表示衷心的謝意。詳細參考資料與網站連結,見附錄。
事實上,由於本人長期有看書記讀書筆記的習慣,所以書中引用筆記的內容,也極有可能是來自某本書或某個朋友的部落格、某個網站的文章。而本人已經無法一一說出其引用的地址,但這些作者的智慧同樣對本書的寫作帶來了幫助,在此只能說聲謝謝。
最後,對清華大學出版社的相關工作人員,表示由衷的感謝。
程杰