免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 852 | 回复: 0
打印 上一主题 下一主题

探索產生物件的技巧(3)鬆綁程式內工廠與產品的關聯性 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-09-18 11:28 |只看该作者 |倒序浏览

知道的越多就越容易被影響,所以如果要再進一步避免「Simple Factory Method」的類別受到改變,可使用「Reflection」機制,等到執行期再決定系統的行為。
套用「Simple Factory Method」設計模式,可以降低用戶端程式碼與所欲使用的產品之間的關聯性。
用戶端只需明白各種實際產品所依循的共通規範(產品介面),並且加以運用即可。如此一來,當實際產品有所更動,或產生實際產品的邏輯有所變化時,用戶端程式碼也不致於被這更動影響,這正是「Simple Factory Method」的好處。
但是在系統中,仍舊有某個類別有可能和這兩樣邏輯存在相依性,它就是提供「Simple Factory Method」的這個類別。
在前一回中,我們設計了一個名為AuthenticatorFactory的類別,負責產生各式認證類別的實作。此AuthenticatorFactory介面如下:

createAuthenticator()會產生系統目前所設定相對應的認證類別,以下是一個可能實作的方式:

這個method會利用一連串的if-else
if比對它所支援的產品──也就是認證類別,倘若authType字串與它所支援的類型相符,便產生相對應的Authenticator實作(例如
LDAPAuthentictor)並且回傳。倘若找不到相符者,便回傳null。
我們時常可以在「Simple Factory Method」中看到不是一連串if-else if的判斷述句,就是switch-case的判斷,因為「Simple Factory Method」必須決定要產生那一種產品。
然而,這樣子的寫法尚有缺憾。當我們要新增一項可能的產品,或者判斷方式有所改變時,雖然用戶端程式碼可以逃過更動的命運,但是提供「Simple Factory Method」的類別,卻難以免除修改的宿命。
雖然用戶端程式碼毋需更動,但createAuthenticator()仍舊被改變所擊中,它得加上以下程式:

因為createAuthenticator()知道這些事情,所以當這些事情改變時,就會影響到它。
如果想避免提供「Simple Factory
Method」的類別被改變,需要進一步的技巧。最常運用的是利用所謂「Reflection」機制。何謂「Reflection」?依照
Wikipedia上的解釋,「Reflection」就是在執行時,依據程式碼的抽象特性及執行期行為,能夠隨之更改的程式。
以比喻的方式來說,就是一種能夠自我觀照並修改自身結構及行為的程式。「Reflection」自身便是一門博大精深的學問,我們試著利用最基礎的Reflection,協助更輕易地實作「Simple Factory Method」,並且提供更佳的擴充性。
Rreflection必須由程式語言提供支援,許多現今流行的程式語言,例如Java、C#、Ruby,都提供Reflection的機制。透
過Reflection機制,最明顯的效果便是,系統的行為可以等到執行期才決定,而非編譯時期即已決定。簡單的說,Reflection和動態型別的載
入及運用有關。
在Java中,有個名為Class的類別,用來代表Java中所有被載入的類別,所以它是個類別的「類別」。Class類別提供一個名為forName()的method,可以傳入類別的名稱,而由它回傳該類別名稱相對應的Class物件,例如:

便能夠取得代表LDAPAuthenticator這個類別的Class物件。Class物件提供一個名為newInstance()的
method,能夠產生一個新的、隸屬於該Class的物件。結合以上所提到的兩點,你會猛然發現,其實並不需要在程式中指定究竟要產生那一種類別的物
件,但仍舊能夠產生。例如:

相較於使用new語法,過去在程式中明確的指定欲產生物件的類別名稱:

使用動態類別物件產生方式的前者,並沒有寫明要產生的類別名稱,而是由讀取系統組態設定的方式,由外部讀取要產生的類別名稱,程式碼本身完全和要產生的類別一點關聯都沒有,就算想要改變被產生的類別,也不會影響到這段程式碼。
反觀後者,程式碼本身「寫死」了要產生的類別名稱(上例中的LDAPAuthenticator),所以當你想要改變這件事的時候,就必須修改程式碼。
運用Reflection機制動態產生物件的方式,可以寫成新版的「Simple Factory Method」:

我們捨棄了一長串的if-else-if的寫法,改用了動態生成物件的方式。在利用newInstance()產生出物件後,進一步檢查該物件是否為Authenticator的實作,倘若不是,直接回傳null,否則便進一步將該物件轉型為Authenticator。
在改用這個寫法之後,可以得到一些好處。首先,程式碼不再寫死認證類別的名稱,所以當你要改變認證類別時,並不會影響到這段程式碼(也就是說,毋需再加重新編譯,只需要更動系統組態設定即可)。
再來,這段程式碼並不知道究竟會需要支援多少種認證類別,它只在意,被設在authClassName中的類別,是否實作了
Authenticator介面。也許你的系統今天在第一位客戶設定的authClassName是Customer1Authenticator,但明
天這套系統在第二位客戶端安裝時,要採用的authClassName卻是Customer2Authenticator(因為不同的客戶需要不同的客製
認證方式)。這樣的改變,對系統來說,卻只需要將Customer2Authenticator直接加到程式路徑中,並且設定authClassName
為Customer2Authenticator,毋需更動程式碼。
這意謂著你可以隨意地「掛上」所需的認證類別,雖然「Simple Factory Method」對它們一無所知,卻又無礙於它產生這些認證類別的物件。系統的擴充性因此大為改善。
透過這樣的方式,我們鬆綁了工廠與產品之間的關聯性,製造產品的工廠本身,與它所製造的產品之間的相依性又降得更低。這使得需求的更動對系統造成的衝擊又變得更少。
《作者簡介》王建興
清華大學資訊工程系的博士研究生,研究興趣包括電腦網路、點對點網路、分散式網路管理、以及行動式代理人,專長則是Internet應用系統的開發。曾參與過的開發專案性質十分廣泛而且不同,從ERP、PC Game到P2P網路電話都在他的涉獵範圍之內。
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/32667/showart_384293.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP