設計模式在軟件工程中占有重要地位而JavaMail是Java平台的一個擴展為管理電子郵件提供了統一的應用編程接口本文討論Factory Method設計模式在Javamail中的應用
模式簡介
模式的概念最早是出現在城市建築領域的lexander的一本關於建築的書中明確的給出了模式的概念用來解決在建築中的一些問題後來這個概念逐漸的被計算機科學所采納《Design Patterns: Elements of Reusable ObjectOriented Software》[](以下簡稱《設計模式》)則堪稱設計模式領域的經典書籍之一它開創了軟件工程領域的模式化進程
設計模式的簡單定義就是對於一類重復出現的問題的可重用的解決方案在軟件工程中一個設計模式解決一類軟件設計問題設計模式中許多方法其實很早就出現了並且在應用中也比較多但是直到《設計模式》出來之前並沒有一種統一的認識或者說那時候並沒有對模式形成一個概念這些方法還僅僅是處在經驗階段並沒有能夠被系統的整理形成一種理論
每一個設計模式都系統的命名解釋和評價了面向對象系統中的一個重要的和重復出現的設計這樣我們只要搞清楚這些設計模式就可以完全或者說很大程度上吸收了那些蘊含在模式中的寶貴的經驗對面向對象的系統能夠有更為完善的了解更為重要的是這些模式都可以直接用來指導面向對象系統中至關重要的對象建模問題如果有相同的問題背景那麼很簡單直接套用這些模式就可以了這可以省去你很多的工作
在《設計模式》一書中涉及到個模式被分類為創建型模式(Creational Patterns)結構型模式(Structural Patterns)和行為模式(Behavioral Patterns)分別從對象的創建對象和對象間的結構組合以及對象交互這三個方面為面向對象系統建模方法給予了解析和指導
其中創建型設計模式(Creational Patterns)描述怎樣創建一個對象它隱藏對象創建的細節使程序代碼不依賴具體的對象這樣當我們增加一個新的對象時幾乎不需要修改代碼結構型設計模式(Structural Patterns)描述類和對象之間怎麼組織起來形成大的結構主要使用繼承來組織接口或實現行為型設計模式(Behavioral Patterns)描述算法以及對象之間的任務分配它所描述的不僅僅是對象或類的設計模式還有它們之間的通訊模式
設計模式在Java中得到了廣泛應用在《Thinking in Java》[]一書中Bruce Eckel介紹了SingletonPrototypeObserverVisitor等設計模式在Java中的具體應用和實現以下將介紹Factory Method設計模式在Javamail中的應用從中可看出設計模式不僅有助於軟件設計對理解軟件結構也很有幫助
Javamail簡介
經過幾年的發展Java語言已相當成熟並在各領域得到廣泛應用特別是JEETM(JavaTM Platform Enterprise Edition)的出現更是極大地方便了分布式應用程序的創建作為Java平台的一個擴展JavaMail也是JEETM的技術之一為管理電子郵件提供了統一的應用編程接口(APIApplication Programming Interface)它使服務提供者(service providers)可以使用Java語言為它們自己的郵件或消息處理系統提供一致的接口應用程序可以使用這些一致的接口方便地與這些系統通信
以下是一些Javamail API中的抽象類由它們可以組成典型的郵件系統
Message代表一個電子郵件消息
Folder以分級的形式組織消息一個Folder可以包含多條消息多個Folder
Store代表由郵件服務器 target=_blank>服務器管理的消息數據庫一個具體的Store使用一種特殊的訪問協議(如PopStore使用Pop協議IMAPStore使用IMAP協議)並可包含一個或多個Folder
Transport代表一個特殊的傳輸協議一個具體的Transport使用具體的傳輸協議發送消息
設計模式Factory Method
此模式屬於創建型設計模式它只定義創建對象的接口而由它的子類負責創建具體的對象利用子類實例化不同的對象圖一是Factory Method 模式結構的類圖(Class Diagram)其中:
Product 定義了由factory method所創建對象的統一接口
ConcreteProduct 具體的類實現Product接口
Creator 一般為抽象類聲明若干factory method(方法)由它創建類型為Product的對象正因為它能生產對象所以稱為factory methodCreator也可能擁有一個方法創建某個缺省的具體對象
ConcreteCreator 重載factory method以創建某個 ConcreteProduct 的具體實例
也就是說Creator依賴於ConcreteCreator創建Product型的ConcreteProduct對象 Factory method使應用程序代碼只需處理Product接口而與具體的類(ConcreteProduct)無關增強了代碼可重用性因為它獨立於用戶定義的具體的類
src=http://imgeducitycn/img_///jpg border= twffan=done>
Factory Method在Javamail中的應用
src=http://imgeducitycn/img_///jpg border= twffan=done>
圖二指示了Factory Method在Javamail中的應用其中的類Store相當於圖一中的CreatorStore的兩個子類PopStoreIMAPStore相當於圖一中的ConcreteStore類Folder相當於ProductFolder的兩個子類PopFolder和IMAPFolder相當於ConcreteProduct而Store中的方法getFolder就是一個factory method由子類PopStore實例化PopFolder由IMAPStore實例化IMAPFolder
類似的圖二中的Folder相對於Store來說是Product但相對於Messsage卻也是一個Creator其方法getMessage同樣也是factory method
可重用性
src=http://imgeducitycn/img_///jpg border= twffan=done>
上表是使用Factory Method模式創建對象和直接創建對象的比較顯然前者對於創建不同的對象所用的代碼幾乎相同便於代碼重用而後者對於創建不同的對象所用代碼就相差很大想做改動就比較麻煩若想重用就幾乎是不可能的設計可重用的面向對象軟件是十分不易的恰當地運用設計模式則可在一定程度上解決這個問題
可擴展性
如有一種對應與PopIMAP的新的郵件協議NewP則很容易使系統支持這種新的協議擴展Store建立新類NewPStore擴展Folder建立新類NewPFolder擴展Message建立新類NewPMessage就建立起了新協議的大致框架
Parameterized Factory Method在Javamail中的應用
Factroy Method設計模式還有一個變異Parameterized factory method模式對於Parameterized factory method模式其factory method有一參數用於指明需創建的對象的類型這樣一個類的factory method可以創建多種具體類型(ConcreteProduct)的對象與Factory Method相同的是它所創建的對象都具有同樣的接口Product
在Javamail中有一個final static類Session不能創建它的子類通過此類設置和訪問一些特殊的屬性另外此類還擁有若干Parameterized Factory Method可以創建多種對象
可重用性
圖三中的getStore和getTransport都是Parameterized Factory Method以getStore為例給參數以不同的值就能創建不同的對象例如
Code highlighting produced by Actipro CodeHighlighter (freeware)
>
Session session = Session
getDefaultInstance(props
authenticator);
Store store
= session
getStore(
pop
); //實例化Pop
Store
Store store
= session
getStore(
IMAP
); //實例化IMAPStore
如上代碼所示通過給出不同的參數即能實例化不同的對象其代碼重用是相當簡單的
可擴展性
若你新建了一個郵件系統擁有Store的特殊子類NewPStore此類采用特殊的協議NewP並已進行了相關設置如在javamaildefaultproviders文件中設置了
Code highlighting produced by Actipro CodeHighlighter (freeware)
>
protocol = NewP; type = store; class = com
sun
mail
IMAP
NewPStore;
這樣你就可以利用
Session session = Session
getDefaultInstance(props
authenticator);
Store store = session
getStore(
NewP
); //實例化NewStore
創建一個NewPStore型對象
src=http://imgeducitycn/img_///jpg border= twffan=done>
總結
Factory Method及其變異Parameterized factory method 都是極為常用的設計模式在Javamail中還有許多地方使用了Factory Method或Parameterized Factory Method比如類Session中的方法getProvidergetFolder也是Parameterized Factory Method getInstance也可以算是Parameterized Factory Method不過它比較特殊它實例化Session自身而且兩者都很容易實現代碼重用進行系統擴展
但Factory Method模式和Parameterized factory method略有不同對於Factory Method有一個潛在的不利因素那就是為了創建一個特殊的對象必須有相應於Creator的一個子類如上所述創建一個PopFolder對象必須要有一個Store的子類PopStore 創建一個IMAPFolder對象必須要有一個Store的子類IMAPStore而對於Parameterized factory method只需要一個具體的Creator提供不同的參數就能創建不同的對象所以可視實際情況在這兩者之中取捨一般原則是當創建一個具體的Product時確實需要擴展Creator那麼就采用Factory Method如Pop和IMAP是兩者區別比較大的不同的郵件協議PopStore和IMAPStore差異很大創建PopFolder確實需要有一個特殊的Store擴展PopStore對於IMAP也一樣此時就需要采用Factory Method模式而為了創建PopStoreIMAPStore如還是采用Factory Method模式而分別創建了Session的子類PopSessionIMAPSession其意義就不是很大完全是為了創建PopStore而創建PopSessionSessionPopSessionIMAPSession三者代碼幾乎相同可以說是一種代碼冗余
總之應該視具體情況應用適當的設計模式才能充分發揮設計模式應有的作用
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27598.html