一、Active Object模式-接收异步消息的主动对象
Active是主动的意思,因此ActiveObject就是主动对象的意思。所谓主动一般指有自己特有的线程,举例来说,java.lang.Thread类的实例就是一种主动对象。
不过,在Active Object模式中出厂的主动对象可不仅仅有自己特有的线程,它同时还具备可以从外部接收和处理异步消息并根据需要返回处理结果的特征。
Active Object模式中的主动对象会通过自己特有的线程在合适的时机处理从外部接收到的异步消息。
在Active Object中,组成主动对象与许多自然人组成法人类似,即使是java语言这样没有异步消息的编程语言,也可以使用Active Object模式组成实际上能够处理异步消息的主动对象。
二、示例程序
将通过示例程序实现“生成字符串”和“显示字符串”这二种功能的主动对象。
1.示例程序类和接口一览表
类名 | 说明 |
---|---|
Main.java | 测试示例程序的类 |
MakerClientThread.java | 发出“生成字符串”请求的线程 |
DisplayClientThread.java | 发出“显示字符串”请求的线程 |
ActiveObject.java | 定义“主动对象”的接口(API)的接口 |
ActiveObjectFactory.java | 创建“主动对象”的类 |
Proxy.java | 将方法调用转换为MethodRequest对象的类(实现了ActiveObject的接口) |
SchedulerThread.java | 调用execute方法处理 MethodRequest对象的类 |
ActivationQueue.java | 按顺序保存MethodRequest对象的类 |
MethodRequest.java | 表示请求的抽象类 |
MakeStringRequest.java | makeString方法(生成字符串)对应的类,MethodRequest类的子类 |
DisplayStringRequest.java | displayString方法(显示字符串)对应的类,MethodRequest类的子类 |
Result.java | 表示执行结果的抽象类 |
FutureResult.java | 在Future模式中表示执行结果的类 |
RealResult.java | 表示实际的执行结果的类 |
Servant.java | 执行实际处理的类(实现了ActiveObject接口) |
2.示例程序的类图
3.示例程序时序图
4.Main类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:35
* @Description:
*/
public class Main {
public static void main(String[] args) {
ActiveObject activeObject = ActiveObjectFactory.createActiveObject();
new MakerClientThread("Steve Nash", activeObject).start();
new MakerClientThread("Michael Jordan", activeObject).start();
new DisplayClientThread("Ronaldo", activeObject).start();
}
}
5.MakerClientThread类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:35
* @Description:
*/
public class MakerClientThread extends Thread {
private final ActiveObject activeObject;
private final char fillchar;
public MakerClientThread(String name, ActiveObject activeObject) {
super(name);
this.activeObject = activeObject;
this.fillchar = name.charAt(0);
}
public void run() {
try {
for (int i = 0; true; i++) {
//有返回值的调用
Result<String> result = activeObject.makeString(i, fillchar);
Thread.sleep(10);
String value = result.getResultValue();
System.out.println(Thread.currentThread().getName() + ": value = " + value);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
6.DisplayClientThread类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:35
* @Description:
*/
public class DisplayClientThread extends Thread {
private final ActiveObject activeObject;
public DisplayClientThread(String name, ActiveObject activeObject) {
super(name);
this.activeObject = activeObject;
}
public void run() {
try {
for (int i = 0; true; i++) {
//没有返回值的调用
String string = Thread.currentThread().getName() + " " + i;
activeObject.displayString(string);
Thread.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
7.ActiveObject类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:35
* @Description:
*/
public interface ActiveObject {
public abstract Result<String> makeString(int count, char fillchar);
public abstract void displayString(String string);
}
8.ActiveObjectFactory类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:35
* @Description:
*/
public class ActiveObjectFactory {
public static ActiveObject createActiveObject() {
Servant servant = new Servant();
ActivationQueue queue = new ActivationQueue();
SchedulerThread scheduler = new SchedulerThread(queue);
Proxy proxy = new Proxy(scheduler, servant);
scheduler.start();
return proxy;
}
}
9.Proxy类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:35
* @Description:
*/
public class Proxy implements ActiveObject {
private final SchedulerThread scheduler;
private final Servant servant;
public Proxy(SchedulerThread scheduler, Servant servant) {
this.scheduler = scheduler;
this.servant = servant;
}
@Override
public Result<String> makeString(int count, char fillchar) {
FutureResult<String> future = new FutureResult<String>();
scheduler.invoke(new MakeStringRequest(servant, future, count, fillchar));
return future;
}
@Override
public void displayString(String string) {
scheduler.invoke(new DisplayStringRequest(servant, string));
}
}
10.SchedulerThread类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:35
* @Description:
*/
public class SchedulerThread extends Thread {
private final ActivationQueue queue;
public SchedulerThread(ActivationQueue queue) {
this.queue = queue;
}
public void invoke(MethodRequest request) {
queue.putRequest(request);
}
public void run() {
while (true) {
MethodRequest request = queue.takeRequest();
request.execute();
}
}
}
11.ActivationQueue类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:37
* @Description:
*/
public class ActivationQueue {
private static final int MAC_METHOD_REQUEST = 100;
private final MethodRequest[] requestQueue;
private int tail; //下次putRqueset的位置
private int head; //下次takeRequest的位置
private int count; //MethodRequest的数量
public ActivationQueue() {
this.requestQueue = new MethodRequest[MAC_METHOD_REQUEST];
this.head = 0;
this.tail = 0;
this.count = 0;
}
public synchronized void putRequest(MethodRequest request) {
while (count >= requestQueue.length) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
requestQueue[tail] = request;
tail = (tail + 1) % requestQueue.length;
count++;
notifyAll();
}
public synchronized MethodRequest takeRequest() {
while (count <= 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
MethodRequest request = requestQueue[head];
head = (head + 1) % requestQueue.length;
count--;
notifyAll();
return request;
}
}
12.MethodRequest类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:37
* @Description:
*/
abstract class MethodRequest<T> {
protected final Servant servant;
protected final FutureResult<T> future;
protected MethodRequest(Servant servant, FutureResult<T> future) {
this.servant = servant;
this.future = future;
}
public abstract void execute();
}
13.MakeStringRequest类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:38
* @Description:
*/
public class MakeStringRequest extends MethodRequest<String> {
private final int count;
private final char fillchar;
public MakeStringRequest(Servant servant, FutureResult<String> future, int count, char fillchar) {
super(servant, future);
this.count = count;
this.fillchar = fillchar;
}
public void execute() {
Result<String> result = servant.makeString(count, fillchar);
future.setResult(result);
}
}
14.DisplayStringRequest类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:38
* @Description:
*/
public class DisplayStringRequest extends MethodRequest<Object> {
private final String string;
public DisplayStringRequest(Servant servant, String string) {
super(servant, null);
this.string = string;
}
public void execute() {
servant.displayString(string);
}
}
15.Result类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:38
* @Description:
*/
public abstract class Result<T> {
public abstract T getResultValue();
}
16.FutureResult类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:38
* @Description:
*/
public class FutureResult<T> extends Result<T> {
private Result<T> result;
private boolean ready = false;
public synchronized void setResult(Result<T> result) {
this.result = result;
this.ready = true;
notifyAll();
}
public synchronized T getResultValue() {
while (!ready) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result.getResultValue();
}
}
17.RealResult类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:38
* @Description:
*/
public class RealResult<T> extends Result<T> {
private final T resultValue;
public RealResult(T resultValue) {
this.resultValue = resultValue;
}
public T getResultValue() {
return resultValue;
}
}
18.Servant类
package com.viagra.Active_Object_Pattern.Lesson1;
/**
* @Auther: viagra
* @Date: 2019/11/19 20:39
* @Description:
*/
public class Servant implements ActiveObject {
@Override
public Result<String> makeString(int count, char fillchar) {
char[] buffer = new char[count];
for (int i = 0; i < count; i++) {
buffer[i] = fillchar;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return new RealResult<String>(new String(buffer));
}
public void displayString(String string) {
try {
System.out.println("displayString: " + string);
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
19.运行示例程序(每次都不一样)
displayString: Ronaldo 0
Steve Nash: value =
Michael Jordan: value =
Steve Nash: value = S
Michael Jordan: value = M
displayString: Ronaldo 1
Steve Nash: value = SS
displayString: Ronaldo 2
Michael Jordan: value = MM
displayString: Ronaldo 3
Steve Nash: value = SSS
displayString: Ronaldo 4
Michael Jordan: value = MMM
displayString: Ronaldo 5
Steve Nash: value = SSSS
displayString: Ronaldo 6
displayString: Ronaldo 7
Michael Jordan: value = MMMM
displayString: Ronaldo 8
displayString: Ronaldo 9
Steve Nash: value = SSSSS
displayString: Ronaldo 10
displayString: Ronaldo 11
Michael Jordan: value = MMMMM
displayString: Ronaldo 12
displayString: Ronaldo 13
Steve Nash: value = SSSSSS
displayString: Ronaldo 14
displayString: Ronaldo 15
displayString: Ronaldo 16
Michael Jordan: value = MMMMMM
displayString: Ronaldo 17
displayString: Ronaldo 18
displayString: Ronaldo 19
Steve Nash: value = SSSSSSS
displayString: Ronaldo 20
displayString: Ronaldo 21
displayString: Ronaldo 22
Michael Jordan: value = MMMMMMM
displayString: Ronaldo 23
displayString: Ronaldo 24
displayString: Ronaldo 25
displayString: Ronaldo 26
Steve Nash: value = SSSSSSSS
displayString: Ronaldo 27
displayString: Ronaldo 28
displayString: Ronaldo 29
displayString: Ronaldo 30
Michael Jordan: value = MMMMMMMM
displayString: Ronaldo 31
displayString: Ronaldo 32
displayString: Ronaldo 33
displayString: Ronaldo 34
Steve Nash: value = SSSSSSSSS
displayString: Ronaldo 35
displayString: Ronaldo 36
displayString: Ronaldo 37
displayString: Ronaldo 38
Michael Jordan: value = MMMMMMMMM
displayString: Ronaldo 39
displayString: Ronaldo 40
displayString: Ronaldo 41
displayString: Ronaldo 42
displayString: Ronaldo 43
Steve Nash: value = SSSSSSSSSS
displayString: Ronaldo 44
displayString: Ronaldo 45
displayString: Ronaldo 46
displayString: Ronaldo 47
Michael Jordan: value = MMMMMMMMMM
displayString: Ronaldo 48
displayString: Ronaldo 49
displayString: Ronaldo 50
三、Active Object模式中角色
1.Client(委托者)
Client角色调用ActiveObject角色的方法来委托处理,在示例程序中是MakerClinetThread类和DisplayClientThread类。
2.ActiveObject(主动对象)
ActiveObject定义了主动对象向Client提供的接口,在示例程序中是ActiveObject接口类。
3.Proxy(代理人)
Proxy负责将方法调用转换为MethodRequest角色的对象。在示例程序中,是Proxy类。
4.Scheduler
Scheduler负责将Proxy角色传递来的MethodRequest传给ActivationQueue角色,在示例程序中,是SchedulerThread类。
5.MethodRequest
是与来自Client角色的请求对应的角色,在示例程序中,是MethodRequest类。
6.ConcreteMethodRequest
ConcreteMethodRequest是使MethodRequest与具体的方法相对应的角色,在示例程序中是MakeStringRequest类和DisplayStringRequest类。
7.Servant(仆人)
Servant负责实际的处理请求,是示例程序中的Servant类。
8.ActivationQueue(主动列队)
ActivationQueue保存MethodRequest角色的类,是示例程序中的ActivationQueue类。
9.VirtualResult(虚拟结果)
VirtualResult与Future、RealResult角色共同构成了Future模式。是示例程序中的Result类。
10.Future(期货)
Future是Client在获取处理结果时实际调用的角色,是示例程序中的FutureResult类。
11.RealResult(真实结果)
RealResult表示处理结果的角色,Servant角色会创建一个RealResult角色作为处理结果,然后调用Future角色的setRealResult方法将其设置到Future角色中。是示例程序中的RealResult类。