序
在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 {
@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);
}
}
最后是根据类型获取产品的简单工厂:
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:something
Product2 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: something
nil
user> ((simply-factory 2) "something")
Product2 use: something
nil
已经达到了我们之前想要的结果,对不对?让我们再看看调用方法的代码((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/product1
user> (product1 "something")
Product1 use: something
nil
user> (def product2 (simply-factory 2))
#'user/product2
user> (product2 "something")
Product2 use: something
nil
这样子应该就能够和之前的java代码一一对应了,其中
IProduct product1 = SimpleFactory.factory("1");
对应
(def product1 (simply-factory 1))
,而
product1.use("something");
对应
(product1 "something")
这样子是不是就能看得更明白一些了?不过要注意的是,虽然调用形式看起来很类似,但是在
Clojure中product1是个函数,而java中product1是个对象。
分享到:
相关推荐
Clojure调用Java类的一个实例
在今后的软件设计中无论使用Clojure语言,还是坚持使用Java语言,Clojure语言都将与java做比较,哪种是设计软件的最佳方式。 Clojure语言是一个JVM(包括Groovy,Jython和JRuby等语言)的新语言,它提供了活力,...
2前言留代码的开发者回来彻底修复该问题前保持数据不被污染。我将编写的用于解决该问题的小程序转交给了运维团队,他们将该程序运行在了一个 JVM 的安全区域。至此,
Description: Clojure is a dynamic language for the Java Virtual Machine, with a compelling combination of features: Clojure is elegant. Clojure's clean, careful design lets you write programs that ...
clojure.java-time:用于Clojure的Java 8 Date-Time API
是一个模块,用于嵌入Clojure或Java或Groovy程序,通常是那些基于的处理程序。 核心功能 最新版本是v0.5.2,有关更多详细信息,请参见。 与兼容,显然支持那些基于Ring的框架,例如Compojure等。 通过使用Clojure ...
【1】[Clojure编程乐趣](The Joy of Clojure).pdf 【2】Clojure – Functional Programming for the JVM中文版.pdf 【3】Clojure Cookbook.pdf 【4】Clojure Data Analysis Cookbook.pdf 【5】clojure Hand book...
clojure-tensorflow, Java api的Java上的一个极轻层 和 TensorFlowJava互操作上的包装器层,用于处理 TensorFlow 。 正在启动神经网络示例(ns example.core (:require [clojure-tensorflow.ops :a
本书向读者展示了如何采用函数式方案来替代或简化面向对象编程中使用的诸多通用模式,同时还介绍了一些在函数式世界中广泛使用的模式。
[2012] Clojure Programming - Practical Lisp for the Java World.(Chas Emerick, Brian Carper, Christophe Grand).[1449394701].pdf+epub.rar [2012] ClojureScript - Up and Running.(Stuart Sierra, Luke ...
Clear, practical Clojure for the professional programmer Professional Clojure is the experienced developer's guide to functional programming using the Clojure language. Designed specifically to meet ...
clojure-1.6 java jvm
Nginx-Clojure 是一个 Nginx 的模块,用于嵌入 Clojure 或者 Java 或者 Groovy 程序。 可以通过nginx-clojure实现JAVA扩展nginx的功能,如权限验证。
主要特性:从 Java 中保护你的 Clojure 程序,进行安全的互操作,正确的使用外部 Java 库。Typed Clojure 支持关键字映射的使用,类型检测器中包含有用的映射操作,包括关键字查找,添加或者移除关键字,合并映射...
clojure clojure clojureclojure clojure
clojure.java.jdbc 一个低层的Clojure包装器,用于基于JDBC的数据库访问。 该项目是“稳定的”(不再是“活动的”)。 实际上,它已被取代。 有关兼容的高级DSL和迁移库,请参阅。 以前称为clojure.contrib.sql ...
Practical Clojure Clojure语言书籍
gradle-java-clojure-骨架一个调用 Clojure 的 Java 应用程序的基本框架应用程序,具有以下功能: 使用构建工具使用 Gradle 插件main() 在 Java 中包括本地 Java 文件包括未编译的本地 Clojure 文件包括第 3 方 ...