JAVA設(shè)計模式:工廠模式之簡單工廠
序
在java中,設(shè)計模式是多態(tài)和封裝的重要表現(xiàn)形式,采用設(shè)計模式能夠極大地提升可維護(hù)性和可擴(kuò)展性,那么,同樣工作在jvm上面的Clojure能否運用這些模式,或者說是否同樣需要這些模式呢?
注:本文基于jdk1.6和Clojure1.2
簡單工廠
先看看簡單工廠的java代碼:
首先定義產(chǎn)品的接口:
- public interface IProduct {
- /**
- * 使用產(chǎn)品
- * @param msg
- */
- public void use(String msg);
- }
然后是實現(xiàn)了這個接口的兩個具體產(chǎn)品Product1和Product2:
- public class Product1 implements IProduct {
- @Override
- public void use(String msg) {
- System.out.println("Product1 use:"+msg);
- }
- }
- public class Product2 implements IProduct {
- @Override
- public void use(String msg) {
- System.out.println("Product2 use:"+msg);
- }
- }
***是根據(jù)類型獲取產(chǎn)品的簡單工廠:
- public class SimpleFactory {
- /**
- * 根據(jù)產(chǎn)品類型生產(chǎn)產(chǎn)品
- * @param productType
- * @return
- */
- public static IProduct factory(String productType){
- if(productType.equals("1"))
- return new Product1();
- else if(productType.equals("2"))
- return new Product2();
- return null;
- }
- }
這樣,我們在java中就構(gòu)建了能夠生產(chǎn)出兩個不同產(chǎn)品的簡單工廠了。接下來,我們調(diào)用一下:
- /**
- * 簡單工廠調(diào)用
- * @author RoySong - 2011-10-27
- */
- public class SimpleFactoryTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- IProduct product1 = SimpleFactory.factory("1");
- product1.use("something");
- IProduct product2 = SimpleFactory.factory("2");
- product2.use("something");
- }
- }
運行這個調(diào)用程序,我們能夠得到預(yù)期的結(jié)果:
- Product1 use:something
- Product2 use:something
那么,在Clojure中應(yīng)該如何實現(xiàn)呢?
#p#
首先,讓我們再回顧一下采用簡單工廠的目的,這是為了將業(yè)務(wù)對象的產(chǎn)生和業(yè)務(wù)方法的執(zhí)行進(jìn)行解耦,使得業(yè)務(wù)方法執(zhí)行時無須關(guān)注業(yè)務(wù)對象的類型。為了達(dá)到這個目的,我們提取了業(yè)務(wù)對象的接口IProduct(在實際的應(yīng)用中也有可能是一個父類Product),它的里面包含了所有業(yè)務(wù)對象的共同操作use(在實際應(yīng)用中可能不止這一種業(yè)務(wù)操作,當(dāng)然也不叫use)的方法聲明。然后,由SimplyFactory來創(chuàng)建IProduct的實例對象,然后調(diào)用use業(yè)務(wù)方法。在這個時候,調(diào)用方法是無須關(guān)注被調(diào)用的具體是哪個實例對象--Product1還是Product2。
好吧,為了業(yè)務(wù)對象的產(chǎn)生和業(yè)務(wù)方法的執(zhí)行解耦。然后,Clojure中沒有對象一說,方法倒是有,不過叫做函數(shù)。于是,問題解決了,沒有對象,則無須對對象的產(chǎn)生進(jìn)行解耦。本文結(jié)束。
拋開上面的文字游戲不談,實際上Clojure的解決方式更為靈活,這是由其語言特性所決定的。在java中,一切都是對象(除了原始類型),而類和接口是對象的定義,包含了有關(guān)對象動作方式的相關(guān)信息,比如名稱、方法、屬性和事件等。所以,在java應(yīng)用中,能夠使用的最小粒度的東西就是對象,如果需要調(diào)用某個實例方法,首先需要實例化某個對象,然后調(diào)用這個對象的方法;如果需要調(diào)用某個靜態(tài)方法,需要找到靜態(tài)方法所屬的類,然后以類名.方法名的形式來調(diào)用。而在Clojure中,函數(shù)是***類對象,它無須依附對象或者類而存在(實際上,在幾乎所有的函數(shù)式編程語言中都是這樣)。換句話說,我們調(diào)用某個方法無須首先實例化某個對象或者找到某個類。
那么,針對上面的例子,我們可以說,實際上我們需要的是根據(jù)不同的類型獲取兩個不同的業(yè)務(wù)處理方法而已。
- (defn simply-factory [type]
- (cond
- (= 1 type) (fn [msg] (println "Product1 use:" msg))
- (= 2 type) (fn [msg] (println "Product2 use:" msg))))
在上面的代碼中,我們定義了一個函數(shù)simply-factory,它接受一個參數(shù)type,然后根據(jù)type的值為1或者2返回對應(yīng)的函數(shù)。實際上,我們從內(nèi)容上可以看出來,這兩個函數(shù)就分別對應(yīng)了之前我們定義的Product1和Product2中的use方法。
接下來,我們就看看調(diào)用和產(chǎn)生的輸出:
- user> ((simply-factory 1) "something")
- Product1 use: something
- nil
- user> ((simply-factory 2) "something")
- Product2 use: something
- nil
已經(jīng)達(dá)到了我們之前想要的結(jié)果,對不對?讓我們再看看調(diào)用方法的代碼((simply-factory 1) "something"),(simply-factory 1)代表傳入?yún)?shù)1調(diào)用simply-factory函數(shù),返回的是一個匿名函數(shù);而((simply-factory 1) "something")整體就代表將"something"傳入simply-factory函數(shù)返回的匿名函數(shù),然后我們就得到了預(yù)期的結(jié)果:Product1 use: something。我相信你已經(jīng)看出來了,Clojure中函數(shù)的調(diào)用方式是:(函數(shù)名 參數(shù))這個樣子的。
不過這個樣子跟上面的java代碼似乎差別有點大,讓我們對這個調(diào)用方式做一點小小的修改:
- user> (def product1 (simply-factory 1))
- #'user/product1
- user> (product1 "something")
- Product1 use: something
- nil
- user> (def product2 (simply-factory 2))
- #'user/product2
- user> (product2 "something")
- Product2 use: something
- nil
這樣子應(yīng)該就能夠和之前的java代碼一一對應(yīng)了,其中
- IProduct product1 = SimpleFactory.factory("1");
對應(yīng)
- (def product1 (simply-factory 1))
,而
- product1.use("something");
對應(yīng)
- (product1 "something")
這樣子是不是就能看得更明白一些了?不過要注意的是,雖然調(diào)用形式看起來很類似,但是在Clojure中product1是個函數(shù),而java中product1是個對象。
原文鏈接:http://songry.iteye.com/blog/1218694
編輯推薦: