设计模式- 主动对象(Active Object)

以下两段文言摘抄自https://blog.csdn.net/qq276592716/article/details/19421359

流程
对每一个要求并发执行的对象,分离其方法的调用和执行。这样,这个对象的客户就像是调用一个常规的方法一样。这个方法,自动把任务交给另外的线程完成执行。
主动对象的组成:一个代理者(Proxy)实现外部的访问接口;一个执行者(Servant)。代理和执行者在不同的线程执行,分离方法调用和执行的过程:代理者在客户线程中被调用执行,执行者在另外的线程完成操作。运行时,代理者把客户的调用信息封装“调用请求”(Method Request),通过调度者(Scheduler)把这个请求放到一个活动队列(Activation Queue)。调度者和执行者运行在另外的线程中,这个线程启动后,不断地从活动队列中得到“调用请求”对象,派发给执行者完成客户请求的操作。客户调用代理者后马上得到一个预约容器(Future),今后可以通过这个预约容器得到返回的结果。

结构
下面使用Booch风格的类图,对主动对象的组成结构进行说明。(译者注:这是Booch在《面向对象的分析和设计》书中使用的类图风格)

在这个模式中,共有六个参与者。
代理者(Proxy)
代理者定义了被客户调用的接口。这个接口是函数调用的方式,而不是像传统线程通信,使用数据传递的方式。当函数被调用的,代理者构造一个“调用请求”对象,并把它放到活动队列中,这一切都发生在客户线程中。

调用请求(Method Request)
“调用请求”用来保存相关函数调用的部上下文信息,比如函数标识,函数的参数,这些信息将在不同线程间传递。一个抽象的“调用请求”类,定义了执行活动对象方法的接口Call。并且包含一个Guard函数,Guard用来检查调用的条件是否满足。对代理者提供的每一个主动对象方法,在访问其执行者的时候需要条件判断。代理者被调用的时候会创建具体“调用请求”对象,对象中包含了执行这个方法必须的参数和数据的返回方式。

活动队列(Activation Queue)
这个队列维护了一个缓冲区(译者注:不一定是先进先出的队列),缓冲区中存放了待执行的“调用请求”。正是这个队列分离可客户线程和执行操作的线程。

调度者(Scheduler)
调度者管理活动队列。调度者决定队列中的哪一个调用请求先被执行。调度的决定可能决定与多个规则:关键字顺序,入队的顺序,要满足的执行条件或等待发生的事件,如:在一个数据结构中出现空闲区。调度者使用Guard方法的调用,来检查是否满足执行条件。

执行者(Servant)
真正完成操作的对象。执行者实际完成代理者定义的主动对象方法,响应一个“调用请求”。调度者给“调用请求”分派一共执行者,然后调用“调用请求”中的Call方法。对应的执行者的方法将被调用。执行者的方法运行在调度者的线程中。执行者可能同时提供了一些方法供“调用请求”实现Guard。

预约容器(Future)
当执行者完成操作,客户通过预约容器获取返回结果。当客户调用代理者的方法后,一共空预约容器马上返回。预约容器指向一块内存空间,用来保存返回结果。客户可以通过轮训或阻塞调用的方法,通过预约容器得到返回结果。

UML图
在这里插入图片描述

其实个人理解一部分就是,它是用来读写分离的好东西。

public interface ActiveObjects {

    Result makeString(int count, char fillChar);

    void displayString(String text);
}
/**
 * 执行者
 */
public class Servant implements ActiveObjects {

    @Override
    public Result makeString(int count, char fillChar) {
        char[] buf = new char[count];
        for(int i = 0; i < count; i++){
            buf[i] = fillChar;
        }
        return new RealResult(new String(buf));
    }

    @Override
    public void displayString(String text) {
        System.out.println("display: " + text);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

返回结果

public interface Result {

    Object getResultValue();
}
public class RealResult implements Result {

    private final Object resultValue;

    public RealResult(Object resultValue) {
        this.resultValue = resultValue;
    }

    @Override
    public Object getResultValue() {
        return this.resultValue;
    }
}
public class FutureResult implements Result {

    private Result result;

    private boolean ready = false;

    public synchronized void setResult(Result result) {
        this.result = result;
        this.ready = true;
        this.notifyAll();
    }

    @Override
    public synchronized Object getResultValue() {
        while(!ready){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return this.result.getResultValue();
    }
}
/**
 * 代理者把客户的调用信息封装“调用请求”
 */
public abstract class MethodRequest {

    protected final Servant servant;

    protected final FutureResult futureResult;

    public MethodRequest(Servant servant, FutureResult futureResult) {
        this.servant = servant;
        this.futureResult = futureResult;
    }

    public abstract void execute();
    
}

下面是具体的make 和 display操作

public class MakeStringRequest extends MethodRequest {

    private final int count;
    private final char fillChar;

    public MakeStringRequest(Servant servant, FutureResult futureResult, int count, char fillChar) {
        super(servant, futureResult);
        this.count = count;
        this.fillChar = fillChar;
    }

    @Override
    public void execute() {
        Result result = servant.makeString(count, fillChar);
        futureResult.setResult(result);
    }
}
public class DisplayStringRequest extends MethodRequest {

    private final String text;

    public DisplayStringRequest(Servant servant, final String text) {
        super(servant, null);
        this.text = text;
    }

    @Override
    public void execute() {
        this.servant.displayString(text);
    }
}

把请求放到( 消费者和生产者)

public class ActivationQueue {

    private final static int MAX_METHOD_REQUEST_QUEUE_SIZE = 100;

    private final LinkedList<MethodRequest> methodQueue = new LinkedList<>();

    public ActivationQueue() {
    }

    public synchronized void put(MethodRequest request){
        while(methodQueue.size() >= MAX_METHOD_REQUEST_QUEUE_SIZE){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.methodQueue.addLast(request);
        this.notifyAll();
    }

    public synchronized MethodRequest take(){
        while(methodQueue.isEmpty()){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        MethodRequest methodRequest = methodQueue.removeFirst();
        this.notifyAll();
        return methodRequest;
    }
}

线程队列

public class SchedulerThread extends Thread
{

    private final ActivationQueue activationQueue;

    public SchedulerThread(ActivationQueue activationQueue) {
        this.activationQueue = activationQueue;
    }

    public void invoke(MethodRequest request){
        this.activationQueue.put(request);
    }

    @Override
    public void run() {
        while(true){
            activationQueue.take().execute();
        }
    }
}

代理者,实现外部接口访问

/**
 * 代理者,实现外部接口访问
 */
public class ActiveObjectProxy implements ActiveObjects {

    private final SchedulerThread schedulerThread;

    private final Servant servant;

    public ActiveObjectProxy(SchedulerThread schedulerThread, Servant servant) {
        this.schedulerThread = schedulerThread;
        this.servant = servant;
    }

    @Override
    public Result makeString(int count, char fillChar) {
        FutureResult futureResult = new FutureResult();
        schedulerThread.invoke(new MakeStringRequest(servant,futureResult,count,fillChar));
        return futureResult;
    }

    @Override
    public void displayString(String text) {
        schedulerThread.invoke(new DisplayStringRequest(servant,text));
    }
}

外部工厂来创建对象

public class ActiveObjectFactory {

    private ActiveObjectFactory() {

    }

    public static ActiveObjects createActiveObject(){
        Servant servant = new Servant();
        ActivationQueue queue = new ActivationQueue();
        SchedulerThread schedulerThread = new SchedulerThread(queue);
        ActiveObjectProxy proxy = new ActiveObjectProxy(schedulerThread, servant);
        schedulerThread.start();
        return proxy;
    }
}

创建两个客户端

public class DisplayClientThread extends Thread{

    private final ActiveObjects activeObjects;

    public DisplayClientThread(String name , ActiveObjects activeObjects) {
        super(name);
        this.activeObjects = activeObjects;
    }

    @Override
    public void run() {
        for (int i= 0;true;i++){
            String text = Thread.currentThread().getName() + "=>" + i;
            activeObjects.displayString(text);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
                //break;
            }
        }
    }
}
public class MakerClientThread extends Thread {

    private final ActiveObjects activeObjects;
    private final char fillchar;

    public MakerClientThread(ActiveObjects activeObjects, String name) {
        super(name);
        this.activeObjects = activeObjects;
        this.fillchar = name.charAt(0);
    }

    @Override
    public void run() {
        try{
            for (int i = 0; true;i++){
                Result result = activeObjects.makeString(i + 1, fillchar);
                Thread.sleep(200);
                String resultValue = (String) result.getResultValue();
                System.out.println(Thread.currentThread().getName() + " " + resultValue);
            }
        }catch (Exception e){

        }
    }
}

测试

public class Test {

    public static void main(String[] args) {

        ActiveObjects activeObject = ActiveObjectFactory.createActiveObject();
        new MakerClientThread(activeObject, "Alice").start();
        new MakerClientThread(activeObject, "mike").start();
        new DisplayClientThread("chris", activeObject).start();
    }
}
发布了68 篇原创文章 · 获赞 6 · 访问量 6668

猜你喜欢

转载自blog.csdn.net/renguiriyue/article/details/104804448