首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

Clojure跟JAVA设计模式(1) 工厂模式之简单工厂

2012-09-28 
Clojure和JAVA设计模式(1) 工厂模式之简单工厂序???? 在java中,设计模式是多态和封装的重要表现形式,采用

Clojure和JAVA设计模式(1) 工厂模式之简单工厂

?

??? 在java中,设计模式是多态和封装的重要表现形式,采用设计模式能够极大地提升可维护性和可扩展性,

那么,同样工作在jvm上面的Clojure能否运用这些模式,或者说是否同样需要这些模式呢?

?

注:本文基于jdk1.6和Clojure1.2

简单工厂

?? 先看看简单工厂的java代码:

?

??? 首先定义产品的接口:

public interface IProduct {/** * 使用产品 * @param msg */public void use(String msg);}

?

?然后是实现了这个接口的两个具体产品Product1和Product2:

public class Product1 implements IProduct {@Overridepublic void use(String msg) {System.out.println("Product1 use:"+msg);}}public class Product2 implements IProduct {@Overridepublic void use(String msg) {System.out.println("Product2 use:"+msg);}}

?

最后是根据类型获取产品的简单工厂:

public class SimpleFactory {/** * 根据产品类型生产产品 * @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中就构建了能够生产出两个不同产品的简单工厂了。接下来,我们调用一下:

?

/** * 简单工厂调用 * @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");}}

?运行这个调用程序,我们能够得到预期的结果:

Product1 use:somethingProduct2 use:something
?

??? 那么,在Clojure中应该如何实现呢?

?

??? 首先,让我们再回顾一下采用简单工厂的目的,这是为了将业务对象的产生和业务方法的

执行进行解耦,使得业务方法执行时无须关注业务对象的类型。为了达到这个目的,我们提取

了业务对象的接口IProduct(在实际的应用中也有可能是一个父类Product),它的里面包含

了所有业务对象的共同操作use(在实际应用中可能不止这一种业务操作,当然也不叫use)

的方法声明。然后,由SimplyFactory来创建IProduct的实例对象,然后调用use业务方法。

在这个时候,调用方法是无须关注被调用的具体是哪个实例对象--Product1还是Product2。

?

????好吧,为了业务对象的产生和业务方法的执行解耦。然后,Clojure中没有对象一说,方法

倒是有,不过叫做函数。于是,问题解决了,没有对象,则无须对对象的产生进行解耦。本文结束。

?

??? 抛开上面的文字游戏不谈,实际上Clojure的解决方式更为灵活,这是由其语言特性所决定的。

在java中,一切都是对象(除了原始类型),而类和接口是对象的定义,包含了有关对象动作方式

的相关信息,比如名称、方法、属性和事件等。所以,在java应用中,能够使用的最小粒度的东西

就是对象,如果需要调用某个实例方法,首先需要实例化某个对象,然后调用这个对象的方法;如

果需要调用某个静态方法,需要找到静态方法所属的类,然后以类名.方法名的形式来调用。而在

Clojure中,函数是第一类对象,它无须依附对象或者类而存在(实际上,在几乎所有的函数式编程

语言中都是这样)。换句话说,我们调用某个方法无须首先实例化某个对象或者找到某个类。

?

??? 那么,针对上面的例子,我们可以说,实际上我们需要的是根据不同的类型获取两个不同的业务

处理方法而已。

(defn simply-factory [type](cond  (= 1 type) (fn [msg] (println "Product1 use:" msg))  (= 2 type) (fn [msg] (println "Product2 use:" msg))))
?

????在上面的代码中,我们定义了一个函数simply-factory,它接受一个参数type,然后根据type的

值为1或者2返回对应的函数。实际上,我们从内容上可以看出来,这两个函数就分别对应了之前我们

定义的Product1和Product2中的use方法。

?

????接下来,我们就看看调用和产生的输出:

user> ((simply-factory 1) "something")Product1 use: somethingniluser> ((simply-factory 2) "something")Product2 use: somethingnil
?

??? 已经达到了我们之前想要的结果,对不对?让我们再看看调用方法的代码((simply-factory 1) "something"),

(simply-factory 1)代表传入参数1调用simply-factory函数,返回的是一个匿名函数;而

((simply-factory 1) "something")整体就代表将"something"传入simply-factory函数返回的匿名函数,然后

我们就得到了预期的结果:Product1 use: something。我相信你已经看出来了,Clojure中函数的调用方式是:

(函数名 参数)这个样子的。

?

????不过这个样子跟上面的java代码似乎差别有点大,让我们对这个调用方式做一点小小的修改:

user> (def product1 (simply-factory 1))#'user/product1user> (product1 "something")Product1 use: somethingniluser> (def product2 (simply-factory 2))#'user/product2user> (product2 "something")Product2 use: somethingnil
?

????这样子应该就能够和之前的java代码一一对应了,其中

IProduct product1 = SimpleFactory.factory("1");

????对应

(def product1 (simply-factory 1))

??? ,而

product1.use("something");

????对应

(product1 "something")

?

????这样子是不是就能看得更明白一些了?不过要注意的是,虽然调用形式看起来很类似,但是在

Clojure中product1是个函数,而java中product1是个对象。

热点排行