意图
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用性
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
Java实现
表现在代码层面就是一个工厂可以返回多个不同的实例!
比如:Pig不仅分颜色,还分国家,比如荷兰Pig,新西兰Pig。
public class RedPigFactory implements PigFactory{
public Pig getNetherlandsPig(){
return new RedNetherlandsPig();
}
public Pig getNewZealandPig(){
return new RedNewZealandPig();
}
}
意图
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
适用性
- 当一个类不知道它所必须创建的对象的类的时候。
- 当一个类希望由它的子类来指定它所创建的对象的时候。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
Java实现
public interface Pig{
public void run();
}
public interface PigFactory{
public Pig getPig();
}
public class RedPig{
public void run(){
System.out.println("RedPig run");
}
}
public class RedPigFactory implements PigFactory{
public Pig getPig(){
return new RedPig();
}
}
public class GreenPig{
public void run(){
System.out.println("GreenPig run");
}
}
public class GreenPigFactory implements PigFactory{
public Pig getPig(){
return new GreenPig();
}
}
概述
设计模式是什么?如果要我现在来回答,那我的答案是:设计模式是对于语言本身缺陷的一种补充!
本系列文章通过对各个设计模式在Java与Clojure之间的实现比较来说明这一点!
关于Clojure相关内容,可以查看这里!
其实使用Clojure来实现设计模式并不合适!因为Clojure是函数式语言,而设计模式是针对面向对象语言的。但是Clojure能提供近似的解决方案或者根本不需要此设计模式,且Clojure的解决方案更简单!简单到都不好意思叫做模式!
当然我也不是要黑Java,毕竟还要靠Java吃饭!Java作为工业化标准开发还是很不错的,只是表现力不足,模板代码较多而已!但是足够简单,易标准化。这就够了!
废话不多说,开始第一个设计模式!单例模式!
意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
适用性
- 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
- 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
Java实现
懒汉式:
public class Singleton{
private Singleton(){}
public synchronized static Singleton getInstance(){
if(single==null){
single=new Singleton();
}
return single;
}
private static Singleton single;
}
本文翻译自:Casting SPELs in Clojure
准备
任何学过Lisp的人都会说Lisp和其它语言有很大的不同.它有很多不可思议的地方.本文将告诉你它有哪些独特之处!
本文适用于Clojure,它是一个运行在JVM上的Lisp方言.Clojure的API和语法和
Common Lisp很类似,但是还是有足够多的区别,需要单独为其写个教程.
在大部分情况下,我们会说Lisp而不是Clojure,因为大部分的概念在Lisp中是通用的.我们会指出Clojure特有的内容.
Clojure是运行在JVM之上的,所以你需要先安装JVM.如果你是MAC机,那么Java已经被安装过了.如果是Linux或者Windows系统,你需要到Oracle Java官网下载对应版本的Java.
而Clojure,你可以从它的官网获得最新版本.下载完成后,你只需要解压缩,打开命令行,切换到解压缩目录,输入:
如果没有问题,那么你将会看到Clojure输出提示
教程中有很多Clojure代码片段,类似下面的样子:
你只需要将这些代码片段拷贝到Clojure REPL中运行就可以了!当你学习完此教程,你将会有一个你自己的文字冒险游戏了!
翻译自Growing a DSL with Clojure.主要讲解如何使用
Clojure来创建一个简单的DSL.包括如下知识点:
- 多重方法(Multimethods)
- 继承(Hierarchies)
- 元编程及"代码即数据"哲学(Metaprogramming and the "Code as data" philosophy)
Lisp及其方言(比如Clojure)可以很方便的创建DSL并能和源语言无缝的集成.
Lisp界鼓吹的优点中,提到最多的可能就是:数据即代码,代码即数据了。在此文中我们将依此特性来定义一个DSL。
我们将渐进式的开发这个DSL,不断的加入Clojure的特性和抽象。
任务
我们的目标是定义一个可以生成各种脚本语言的DSL.而且DSL代码看起来和普通的Clojure代码没有区别。
例如,我们使用Clojure形式(form)来生成Bash脚本或者Windows批处理脚本:
输入(Clojure形式):
(if (= 1 2)
(println "a")
(println "b"))
输出(Bash脚本):
if [ 1 -eq 2 ]; then
echo "a"
else
echo "b"
fi
输出(Windows批处理):
IF 1==2 (
ECHO a
) ELSE (
ECHO b
)
版本
本文翻译自Clojure Namespaces and Vars
本文涵盖如下内容:
- Clojure命名空间和var概述
- 如何定义命名空间
- 如何使用其它命名空间里的函数
- require,refer和use
- 常见错误和典型错误,以及导致这些错误的原因
- 命名空间和代码管理
版权:
This work is licensed under a Creative Commons Attribution 3.0 Unported License (including images & stylesheets). The source is available on Github.
涵盖Clojure版本:Clojure 1.5
概述
Clojure的函数通过命名空间来组织.Clojure命名空间和Java的包或者Python的模块很类似.命名空间实际上就是个map,将名字映射到了var上.在大部分情况下,这些var持有这些函数.
定义一个命名空间
一般情况下使用clojure.core/ns宏来定义命名空间.最基本的形式下,它将名字作为符号.
命名空间可以由点号切割的好多段组成
(ns megacorp.service.core)
需要注意的是,请尽量避免使用单段的命名空间,以免与其它开发人员的命名空间相冲突.如果库或者应用属于某个组织,那么建议以如下形式作为命名空间.[组织名称].[包名|应用名].[函数组名]
例如
(ns clojurewerkz.welle.kv)
(ns megacorp.search.indexer.core)