概述
本系列文章意在比较Java与Clojure在线程实现上的区别!
Java的线程主要基于锁机制,而Clojure主要模拟了数据库事务操作,所谓的STM(软事务模型)。主要从代码层面给出两者的区别,孰优孰劣请自行判断!
启动线程
Java代码
- Java实例中,两个线程类A和B,分别通过实现Runnable接口和继承Thread类来实现
- 两各类启动线程的方式有差异,详见代码
- JDK5中提供了线程启动类Executors来执行
package concurrent;
import java.util.concurrent.*;
/**
* Created by ivan on 15-2-22.
* Java启动线程
*/
public class Start {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//实现Runnable接口,需要通过一个Thread实例来启动线程
new Thread(new A()).start();
//继承Thread类,直接通过自身来启动线程
new B().start();
//JDK1.5开始,可以通过Executor来执行线程.效果和上面没有区别
ExecutorService e = Executors.newCachedThreadPool();
e.execute(new A());
e.execute(new B());
//Callable需要submit,返回Future
Future<String> f = e.submit(new C());
//get方法是个阻塞方法
System.out.println("Future f = " + f.get());
e.shutdown();
}
}
意图
提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
适用性
- 访问一个聚合对象的内容而无需暴露它的内部表示。
- 支持对聚合对象的多种遍历。
- 为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。
Java实现
Java提供了Iterable接口,直接实现此接口即可!
public class AList implements Iterable{
...
private int idx;
public static void main(String[] args) {
AList list = new AList();
list.add(1);
list.add(2);
list.add(3);
for(Object o : list){
System.out.println(o);
}
}
@Override
public Iterator iterator() {
return new Iterator() {
@Override
public boolean hasNext() {
return idx < length;
}
@Override
public Object next() {
return arr[idx++];
}
};
}
}
意图
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
适用性
- 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
- 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
Java实现
//访问者
public interface Visitor {
public void visit(Park park);
public void visit(ParkA parkA);
public void visit(ParkB parkB);
}
//清洁工A,负责parkA的卫生情况
public class VisitorA implements Visitor {
public void visit(Park park) {
}
public void visit(ParkA parkA) {
System.out.println("清洁工A:完成公园" + parkA.getName()+ "的卫生");
}
public void visit(ParkB parkB) {
}
}
意图
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用性
- 当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:
- 该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。
- 效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。
Java实现
抽象表达式角色
public abstract class Expression {
/**
* 以环境为准,本方法解释给定的任何一个表达式
*/
public abstract boolean interpret(Context ctx);
/**
* 检验两个表达式在结构上是否相同
*/
public abstract boolean equals(Object obj);
/**
* 返回表达式的hash code
*/
public abstract int hashCode();
/**
* 将表达式转换成字符串
*/
public abstract String toString();
}
意图
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
适用性
- 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
- 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
- 想定制一个分布在多个类中的行为,而又不想生成太多的子类。
Java实现
//抽象同事类
public abstract class Person {
// 维持一个抽象中介者的引用
protected Mediator mediator;
protected String name;
public Person(String name, Mediator mediator){
this.mediator = mediator;
this.name = name;
}
/**
* 设置中介者对象
* @param mediator
*/
public void setMediator(Mediator mediator){
this.mediator = mediator;
}
/**
* 向中介 发送消息
*/
protected abstract void sendMessage(String msg);
/**
* 从中介 获取消息
*/
protected abstract void getMessage(String msg);
}
意图
定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
适用性
- 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
- 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式。
- 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
- 一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。
Java实现
public class Context {
//持有一个具体策略的对象
private Strategy strategy;
/**
* 构造函数,传入一个具体策略对象
* @param strategy 具体策略对象
*/
public Context(Strategy strategy){
this.strategy = strategy;
}
/**
* 策略方法
*/
public void contextInterface(){
strategy.strategyInterface();
}
}
意图
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
适用性
- 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常, 有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
Java实现
public class Order{
private State unPayState;
private State payedState;
private State sendState;
private State doneState; //四种状态,四种类,对应的get,set方法省略
private State state = unPayState; //当前状态
public Order(){
unPayState = new UnPayState(this);
payedState = new PayedState(this); //传入Order对象,为了修改Order的状态
...
}
public void pay(){
state.pay();
}
public void send(){
state.send();
}
....
}