在Te2和IWS的開發過程中,我終於體會到了采用組件開發的方式給我帶來的非凡的快樂和巨大的痛苦,一方面,我可以簡單的拖拉幾個組件放在Form或者DataModule上,設置一下屬性,接著我就可以按F9來Run了。另一方面,我常常陷於莫名其妙的AV錯誤中,一不小心就會把我的Delphi搞崩潰。但是,只要我們搞清楚了創建組件的一些基本方法,那麼就可以小心的避開組件開發過程中的種種陷阱。在閱讀這篇文章之前,我建議大家可以先讀:
- Delphi愛好者上的:Form Class To Component,這篇文檔告訴我們創建組件的基本方法
- Creating Components Dynamically,這篇文檔告訴我們使用組件的正確方法
- Dynamic Component Creation Gotcha (Don't Do This),這篇文檔告訴我們使用組件的負作用
- Reuse through Inheritance and Composition,這篇文檔告訴我們如何設計組件
- 10 guidelines to help you design for reuse,這篇文檔也告訴我們設計組件一些可以操作的辦法
我寫這篇文章的目的是希望我們能從過去的RAD開發方式中轉變成基於組件的開發方式,但是這篇文檔並不告訴大家如何寫組件,及寫組件的一些方法,因為那幾乎可以寫成一本書了。
為什麼用組件?
現在開發領域中比較熱門的話題是OO及基於OO的更加偏重於問題域的Patterns,在我剛剛開始使用Delphi的時,我常常自問:我采用了OOP嗎?讓我們來看看使用Delphi 開發的標准方式:往Form或DataModule上放置幾個組件,寫幾個事件,按F9 Run 。是的,RAD令我愉快的編程,但是它不會導致我認真設計:
- 開始階段代碼並不會復雜,好多時候我們會把一些通用的代碼拷貝到程序的各個地方,而且這些代碼看起來好象不能復用,最簡單的例子就是:在某個Action的Execute事件中我創建一個Query,執行一個SQL,在另一個Action的Execute事件中我又會創建一個Query去執行另一個SQL,這裡有沒有什麼辦法來抽象創建Query的過程?
- Object Inspector非常好用,我可以非常容易的寫事件處理邏輯,但是這會把邏輯和Form或DataModule緊緊綁定。盡管把業務邏輯寫在DataModule中是Delphi推薦的方式,但它的復用程度並不怎麼好,想想在一個DataModule中放置幾十個數據集的情況,你還能說這個DataModule可以復用嗎?
所以,我推薦使用基於組件的編程,Why,讓我們看看Form Class To Component中寫到使用組件的三個優點:
- Delphi有一套組件的動態創建和銷毀的機制,反之,TObject的派生類必須顯式的在代碼中創建、使用、銷毀。
- 你可以在設計時設置屬性,不要小看這個優點,我們可以開發出屬性編輯器,可以讓用戶只能選擇合法的屬性值。
- 對於可視組件,你可以在設計時設置組件的位置和大小。
這只是顯而易見的優點,它只是表象,隱藏在這些優點下面的精髓是:OOP。Delphi提供了一個組件框架,所以當你開始試圖通過寫組件來簡化編程的時候,你就會不知不覺的采用OO的編程方法。最為重要的是VCL框架采用了許多讓程序易於重用的設計模式:
- Composite 模式:當你在Form上放置各種組件,組成一個新的TForm的派生類,你用到了Composite 模式
- Builder 模式:當你創建你定義的Form時,你會使用Builder模式,通常Builder模式創建的對象是由Composite模式組成的。
- Template Method 模式:這個模式太普遍了,任何一個從TComponent的派生的類,都會使用該模式!
- Mediator 模式 :當你寫事件時,你用的正是Mediator 模式,注意了Mediator 模式中的缺點就是:它會使中介者為一個龐然大物!
- Singleton 模式:盡管沒有任何機制阻止我們創建多個TApplicaion對象,但是我們知道任何一個GUI程序只能有一個TApplcaiton對象,那就是全局變量Applicaion。
當你開發組件時,你已經開始使用OOP,並且將會使用上面的五種模式。至少從理論上已經保證你的代碼是可以重用的,你的程序是易於更改從而適應更多的需求。