設計模式在軟件工程中占有重要地位,而JavaMail是Java平臺的一個擴展,為管理電子郵件提供了統(tǒng)一的應用編程接口。本文討論Factory Method設計模式在Javamail中的應用。
1、模式簡介
模式的概念最早是出現(xiàn)在城市建筑領域的。lexander的一本關于建筑的書中明確的給出了模式的概念,用來解決在建筑中的一些問題。后來,這個概念逐漸的被計算機科學所采納?!禗esign Patterns: Elements of Reusable Object-Oriented Software》[1](以下簡稱《設計模式》)則堪稱設計模式領域的經(jīng)典書籍之一。它開創(chuàng)了軟件工程領域的模式化進程。
設計模式的簡單定義就是對于一類重復出現(xiàn)的問題的可重用的解決方案。在軟件工程中一個設計模式解決一類軟件設計問題。設計模式中許多方法其實很早就出現(xiàn)了,并且在應用中也比較多。但是直到《設計模式》出來之前,并沒有一種統(tǒng)一的認識?;蛘哒f,那時候并沒有對模式形成一個概念。這些方法還僅僅是處在經(jīng)驗階段,并沒有能夠被系統(tǒng)的整理,形成一種理論。
每一個設計模式都系統(tǒng)的命名,解釋和評價了面向對象系統(tǒng)中的一個重要的和重復出現(xiàn)的設計。這樣,我們只要搞清楚這些設計模式,就可以完全或者說很大程度上吸收了那些蘊含在模式中的寶貴的經(jīng)驗,對面向對象的系統(tǒng)能夠有更為完善的了解。更為重要的是,這些模式都可以直接用來指導面向對象系統(tǒng)中至關重要的對象建模問題。如果有相同的問題背景,那么很簡單,直接套用這些模式就可以了。這可以省去你很多的工作。
在《設計模式》一書中涉及到23個模式,被分類為創(chuàng)建型模式(Creational Patterns),結構型模式(Structural Patterns)和行為模式(Behavioral Patterns),分別從對象的創(chuàng)建,對象和對象間的結構組合以及對象交互這三個方面為面向對象系統(tǒng)建模方法給予了解析和指導。
其中創(chuàng)建型設計模式(Creational Patterns)描述怎樣創(chuàng)建一個對象。它隱藏對象創(chuàng)建的細節(jié),使程序代碼不依賴具體的對象,這樣當我們增加一個新的對象時幾乎不需要修改代碼。結構型設計模式(Structural Patterns)描述類和對象之間怎么組織起來形成大的結構,主要使用繼承來組織接口或實現(xiàn)。行為型設計模式(Behavioral Patterns)描述算法以及對象之間的任務分配,它所描述的不僅僅是對象或類的設計模式,還有它們之間的通訊模式。
設計模式在Java中得到了廣泛應用。在《Thinking in Java》[3]一書中,Bruce Eckel介紹了Singleton、Prototype、Observer、Visitor等設計模式在Java中的具體應用和實現(xiàn),以下將介紹 Factory Method設計模式在Javamail中的應用。從中可看出設計模式不僅有助于軟件設計,對理解軟件結構也很有幫助。
2、Javamail簡介
經(jīng)過幾年的發(fā)展,Java語言已相當成熟,并在各領域得到廣泛應用。特別是J2EETM(JavaTM 2 Platform, Enterprise Edition)的出現(xiàn),更是極大地方便了分布式應用程序的創(chuàng)建。作為Java平臺的一個擴展--JavaMail,也是J2EETM的技術之一,為管理電子郵件提供了統(tǒng)一的應用編程接口(API,Application Programming Interface)。它使服務提供者(service providers)可以使用Java語言為它們自己的郵件或消息處理系統(tǒng)提供一致的接口,應用程序可以使用這些一致的接口方便地與這些系統(tǒng)通信。
以下是一些Javamail API中的抽象類,由它們可以組成典型的郵件系統(tǒng):
Message-代表一個電子郵件消息。
Folder-以分級的形式組織消息。一個Folder可以包含多條消息、多個Folder。
Store-代表由郵件服務器 target=_blank>服務器管理的消息數(shù)據(jù)庫,一個具體的Store使用一種特殊的訪問協(xié)議(如Pop3Store使用Pop3協(xié)議,IMAPStore使用IMAP協(xié)議),并可包含一個或多個Folder。
Transport-代表一個特殊的傳輸協(xié)議,一個具體的Transport使用具體的傳輸協(xié)議發(fā)送消息。
3、設計模式Factory Method
此模式屬于創(chuàng)建型設計模式,它只定義創(chuàng)建對象的接口,而由它的子類負責創(chuàng)建具體的對象,利用子類實例化不同的對象。Factory Method 模式結構的類圖(Class Diagram),其中:
Product 定義了由factory method所創(chuàng)建對象的統(tǒng)一接口。
ConcreteProduct 具體的類,實現(xiàn)Product接口。
Creator 一般為抽象類,聲明若干factory method(方法),由它創(chuàng)建類型為Product的對象。正因為它能"生產(chǎn)"對象,所以稱為factory method。Creator也可能擁有一個方法創(chuàng)建某個缺省的具體對象。
ConcreteCreator 重載factory method以創(chuàng)建某個 ConcreteProduct 的具體實例。
也就是說Creator依賴于ConcreteCreator創(chuàng)建Product型的ConcreteProduct對象。 Factory method使應用程序代碼只需處理Product接口,而與具體的類(ConcreteProduct)無關,增強了代碼可重用性,因為它獨立于用戶定義的具體的類。
4、Factory Method在Javamail中的應用
Factory Method在Javamail中的應用。其中的類Store相當于Creator,Store的兩個子類 Pop3Store,IMAPStore相當于ConcreteStore,類Folder相當于Product,F(xiàn)older的兩個子類 Pop3Folder和IMAPFolder相當于ConcreteProduct,而Store中的方法getFolder就是一個factory method,由子類Pop3Store實例化Pop3Folder,由IMAPStore實例化IMAPFolder。
類似的Folder相對于Store來說是Product,但相對于Messsage卻也是一個Creator,其方法getMessage同樣也是factory method。
4.1可重用性
上表是使用Factory Method模式創(chuàng)建對象和直接創(chuàng)建對象的比較,顯然前者對于創(chuàng)建不同的對象所用的代碼幾乎相同,便于代碼重用,而后者對于創(chuàng)建不同的對象所用代碼就相差很大,想做改動就比較麻煩,若想重用就幾乎是不可能的。設計可重用的面向對象軟件是十分不易的,恰當?shù)剡\用設計模式則可在一定程度上解決這個問題。
4.2 可擴展性
如有一種對應與Pop3、IMAP的新的郵件協(xié)議NewP,則很容易使系統(tǒng)支持這種新的協(xié)議,擴展Store建立新類NewPStore,擴展 Folder建立新類NewPFolder,擴展Message建立新類NewPMessage,就建立起了新協(xié)議的大致框架。
5、Parameterized Factory Method在Javamail中的應用
Factroy Method設計模式還有一個變異Parameterized factory method模式。對于Parameterized factory method模式,其factory method有一參數(shù),用于指明需創(chuàng)建的對象的類型,這樣一個類的factory method可以創(chuàng)建多種具體類型(ConcreteProduct)的對象,與Factory Method相同的是它所創(chuàng)建的對象都具有同樣的接口Product。
在Javamail中有一個final static類Session,不能創(chuàng)建它的子類,通過此類設置和訪問一些特殊的屬性,另外此類還擁有若干Parameterized Factory Method,可以創(chuàng)建多種對象。
5.1可重用性
getStore和getTransport都是Parameterized Factory Method,以getStore為例,給參數(shù)以不同的值就能創(chuàng)建不同的對象。例如:
1 Session session = Session.getDefaultInstance(props, authenticator);
2
3 Store store1 = session.getStore("pop3"); //實例化Pop3Store
4
5 Store store2 = session.getStore("IMAP"); //實例化IMAPStore
6
7
如上代碼所示,通過給出不同的參數(shù),即能實例化不同的對象,其代碼重用是相當簡單的。
5.2可擴展性
若你新建了一個郵件系統(tǒng),擁有Store的特殊子類NewPStore,此類采用特殊的協(xié)議NewP,并已進行了相關設置,如在javamail.default.providers文件中設置了:
1 protocol = NewP; type = store; class = com.sun.mail.IMAP.NewPStore;
2
3 這樣你就可以利用
4
5 Session session = Session.getDefaultInstance(props, authenticator);
6
7 Store store = session.getStore("NewP"); //實例化NewStore
8
9
創(chuàng)建一個NewPStore型對象。
6、總結
Factory Method及其變異Parameterized factory method 都是極為常用的設計模式。在Javamail中還有許多地方使用了Factory Method或Parameterized Factory Method,比如類Session中的方法getProvider、getFolder也是Parameterized Factory Method, getInstance也可以算是Parameterized Factory Method,加入收藏不過它比較特殊,它實例化Session自身。而且兩者都很容易實現(xiàn)代碼重用,進行系統(tǒng)擴展。
但Factory Method模式和Parameterized factory method略有不同。對于Factory Method,有一個潛在的不利因素,那就是為了創(chuàng)建一個特殊的對象,必須有相應于Creator的一個子類。如上所述創(chuàng)建一個Pop3Folder對象必須要有一個Store的子類Pop3Store, 創(chuàng)建一個IMAPFolder對象必須要有一個Store的子類IMAPStore。而對于Parameterized factory method只需要一個具體的Creator,提供不同的參數(shù)就能創(chuàng)建不同的對象。所以可視實際情況在這兩者之中取舍。一般原則是:當創(chuàng)建一個具體的 Product時確實需要擴展Creator,那么就采用Factory Method,如Pop3和IMAP是兩者區(qū)別比較大的不同的郵件協(xié)議,Pop3Store和IMAPStore差異很大,創(chuàng)建Pop3Folder確實需要有一個特殊的Store擴展--Pop3Store,對于IMAP也一樣,此時就需要采用Factory Method模式。而為了創(chuàng)建Pop3Store、IMAPStore,如還是采用Factory Method模式而分別創(chuàng)建了Session的子類Pop3Session、IMAPSession,其意義就不是很大,完全是為了創(chuàng)建 Pop3Store而創(chuàng)建Pop3Session,Session、Pop3Session、IMAPSession三者代碼幾乎相同,可以說是一種代碼冗余。
總之應該視具體情況應用適當?shù)脑O計模式,才能充分發(fā)揮設計模式應有的作用。
1、模式簡介
模式的概念最早是出現(xiàn)在城市建筑領域的。lexander的一本關于建筑的書中明確的給出了模式的概念,用來解決在建筑中的一些問題。后來,這個概念逐漸的被計算機科學所采納?!禗esign Patterns: Elements of Reusable Object-Oriented Software》[1](以下簡稱《設計模式》)則堪稱設計模式領域的經(jīng)典書籍之一。它開創(chuàng)了軟件工程領域的模式化進程。
設計模式的簡單定義就是對于一類重復出現(xiàn)的問題的可重用的解決方案。在軟件工程中一個設計模式解決一類軟件設計問題。設計模式中許多方法其實很早就出現(xiàn)了,并且在應用中也比較多。但是直到《設計模式》出來之前,并沒有一種統(tǒng)一的認識?;蛘哒f,那時候并沒有對模式形成一個概念。這些方法還僅僅是處在經(jīng)驗階段,并沒有能夠被系統(tǒng)的整理,形成一種理論。
每一個設計模式都系統(tǒng)的命名,解釋和評價了面向對象系統(tǒng)中的一個重要的和重復出現(xiàn)的設計。這樣,我們只要搞清楚這些設計模式,就可以完全或者說很大程度上吸收了那些蘊含在模式中的寶貴的經(jīng)驗,對面向對象的系統(tǒng)能夠有更為完善的了解。更為重要的是,這些模式都可以直接用來指導面向對象系統(tǒng)中至關重要的對象建模問題。如果有相同的問題背景,那么很簡單,直接套用這些模式就可以了。這可以省去你很多的工作。
在《設計模式》一書中涉及到23個模式,被分類為創(chuàng)建型模式(Creational Patterns),結構型模式(Structural Patterns)和行為模式(Behavioral Patterns),分別從對象的創(chuàng)建,對象和對象間的結構組合以及對象交互這三個方面為面向對象系統(tǒng)建模方法給予了解析和指導。
其中創(chuàng)建型設計模式(Creational Patterns)描述怎樣創(chuàng)建一個對象。它隱藏對象創(chuàng)建的細節(jié),使程序代碼不依賴具體的對象,這樣當我們增加一個新的對象時幾乎不需要修改代碼。結構型設計模式(Structural Patterns)描述類和對象之間怎么組織起來形成大的結構,主要使用繼承來組織接口或實現(xiàn)。行為型設計模式(Behavioral Patterns)描述算法以及對象之間的任務分配,它所描述的不僅僅是對象或類的設計模式,還有它們之間的通訊模式。
設計模式在Java中得到了廣泛應用。在《Thinking in Java》[3]一書中,Bruce Eckel介紹了Singleton、Prototype、Observer、Visitor等設計模式在Java中的具體應用和實現(xiàn),以下將介紹 Factory Method設計模式在Javamail中的應用。從中可看出設計模式不僅有助于軟件設計,對理解軟件結構也很有幫助。
2、Javamail簡介
經(jīng)過幾年的發(fā)展,Java語言已相當成熟,并在各領域得到廣泛應用。特別是J2EETM(JavaTM 2 Platform, Enterprise Edition)的出現(xiàn),更是極大地方便了分布式應用程序的創(chuàng)建。作為Java平臺的一個擴展--JavaMail,也是J2EETM的技術之一,為管理電子郵件提供了統(tǒng)一的應用編程接口(API,Application Programming Interface)。它使服務提供者(service providers)可以使用Java語言為它們自己的郵件或消息處理系統(tǒng)提供一致的接口,應用程序可以使用這些一致的接口方便地與這些系統(tǒng)通信。
以下是一些Javamail API中的抽象類,由它們可以組成典型的郵件系統(tǒng):
Message-代表一個電子郵件消息。
Folder-以分級的形式組織消息。一個Folder可以包含多條消息、多個Folder。
Store-代表由郵件服務器 target=_blank>服務器管理的消息數(shù)據(jù)庫,一個具體的Store使用一種特殊的訪問協(xié)議(如Pop3Store使用Pop3協(xié)議,IMAPStore使用IMAP協(xié)議),并可包含一個或多個Folder。
Transport-代表一個特殊的傳輸協(xié)議,一個具體的Transport使用具體的傳輸協(xié)議發(fā)送消息。
3、設計模式Factory Method
此模式屬于創(chuàng)建型設計模式,它只定義創(chuàng)建對象的接口,而由它的子類負責創(chuàng)建具體的對象,利用子類實例化不同的對象。Factory Method 模式結構的類圖(Class Diagram),其中:
Product 定義了由factory method所創(chuàng)建對象的統(tǒng)一接口。
ConcreteProduct 具體的類,實現(xiàn)Product接口。
Creator 一般為抽象類,聲明若干factory method(方法),由它創(chuàng)建類型為Product的對象。正因為它能"生產(chǎn)"對象,所以稱為factory method。Creator也可能擁有一個方法創(chuàng)建某個缺省的具體對象。
ConcreteCreator 重載factory method以創(chuàng)建某個 ConcreteProduct 的具體實例。
也就是說Creator依賴于ConcreteCreator創(chuàng)建Product型的ConcreteProduct對象。 Factory method使應用程序代碼只需處理Product接口,而與具體的類(ConcreteProduct)無關,增強了代碼可重用性,因為它獨立于用戶定義的具體的類。
4、Factory Method在Javamail中的應用
Factory Method在Javamail中的應用。其中的類Store相當于Creator,Store的兩個子類 Pop3Store,IMAPStore相當于ConcreteStore,類Folder相當于Product,F(xiàn)older的兩個子類 Pop3Folder和IMAPFolder相當于ConcreteProduct,而Store中的方法getFolder就是一個factory method,由子類Pop3Store實例化Pop3Folder,由IMAPStore實例化IMAPFolder。
類似的Folder相對于Store來說是Product,但相對于Messsage卻也是一個Creator,其方法getMessage同樣也是factory method。
4.1可重用性
上表是使用Factory Method模式創(chuàng)建對象和直接創(chuàng)建對象的比較,顯然前者對于創(chuàng)建不同的對象所用的代碼幾乎相同,便于代碼重用,而后者對于創(chuàng)建不同的對象所用代碼就相差很大,想做改動就比較麻煩,若想重用就幾乎是不可能的。設計可重用的面向對象軟件是十分不易的,恰當?shù)剡\用設計模式則可在一定程度上解決這個問題。
4.2 可擴展性
如有一種對應與Pop3、IMAP的新的郵件協(xié)議NewP,則很容易使系統(tǒng)支持這種新的協(xié)議,擴展Store建立新類NewPStore,擴展 Folder建立新類NewPFolder,擴展Message建立新類NewPMessage,就建立起了新協(xié)議的大致框架。
5、Parameterized Factory Method在Javamail中的應用
Factroy Method設計模式還有一個變異Parameterized factory method模式。對于Parameterized factory method模式,其factory method有一參數(shù),用于指明需創(chuàng)建的對象的類型,這樣一個類的factory method可以創(chuàng)建多種具體類型(ConcreteProduct)的對象,與Factory Method相同的是它所創(chuàng)建的對象都具有同樣的接口Product。
在Javamail中有一個final static類Session,不能創(chuàng)建它的子類,通過此類設置和訪問一些特殊的屬性,另外此類還擁有若干Parameterized Factory Method,可以創(chuàng)建多種對象。
5.1可重用性
getStore和getTransport都是Parameterized Factory Method,以getStore為例,給參數(shù)以不同的值就能創(chuàng)建不同的對象。例如:
1 Session session = Session.getDefaultInstance(props, authenticator);
2
3 Store store1 = session.getStore("pop3"); //實例化Pop3Store
4
5 Store store2 = session.getStore("IMAP"); //實例化IMAPStore
6
7
如上代碼所示,通過給出不同的參數(shù),即能實例化不同的對象,其代碼重用是相當簡單的。
5.2可擴展性
若你新建了一個郵件系統(tǒng),擁有Store的特殊子類NewPStore,此類采用特殊的協(xié)議NewP,并已進行了相關設置,如在javamail.default.providers文件中設置了:
1 protocol = NewP; type = store; class = com.sun.mail.IMAP.NewPStore;
2
3 這樣你就可以利用
4
5 Session session = Session.getDefaultInstance(props, authenticator);
6
7 Store store = session.getStore("NewP"); //實例化NewStore
8
9
創(chuàng)建一個NewPStore型對象。
6、總結
Factory Method及其變異Parameterized factory method 都是極為常用的設計模式。在Javamail中還有許多地方使用了Factory Method或Parameterized Factory Method,比如類Session中的方法getProvider、getFolder也是Parameterized Factory Method, getInstance也可以算是Parameterized Factory Method,加入收藏不過它比較特殊,它實例化Session自身。而且兩者都很容易實現(xiàn)代碼重用,進行系統(tǒng)擴展。
但Factory Method模式和Parameterized factory method略有不同。對于Factory Method,有一個潛在的不利因素,那就是為了創(chuàng)建一個特殊的對象,必須有相應于Creator的一個子類。如上所述創(chuàng)建一個Pop3Folder對象必須要有一個Store的子類Pop3Store, 創(chuàng)建一個IMAPFolder對象必須要有一個Store的子類IMAPStore。而對于Parameterized factory method只需要一個具體的Creator,提供不同的參數(shù)就能創(chuàng)建不同的對象。所以可視實際情況在這兩者之中取舍。一般原則是:當創(chuàng)建一個具體的 Product時確實需要擴展Creator,那么就采用Factory Method,如Pop3和IMAP是兩者區(qū)別比較大的不同的郵件協(xié)議,Pop3Store和IMAPStore差異很大,創(chuàng)建Pop3Folder確實需要有一個特殊的Store擴展--Pop3Store,對于IMAP也一樣,此時就需要采用Factory Method模式。而為了創(chuàng)建Pop3Store、IMAPStore,如還是采用Factory Method模式而分別創(chuàng)建了Session的子類Pop3Session、IMAPSession,其意義就不是很大,完全是為了創(chuàng)建 Pop3Store而創(chuàng)建Pop3Session,Session、Pop3Session、IMAPSession三者代碼幾乎相同,可以說是一種代碼冗余。
總之應該視具體情況應用適當?shù)脑O計模式,才能充分發(fā)揮設計模式應有的作用。