Active Object模式

Active Object模式通常和command命令模式一起使用。这是一个非常古老的模式。我们先来看一个例子。

// Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <list>
#include <memory>

class Command
{
public:
    virtual void exec() = 0;
};

class Copy : public Command
{
public:
    virtual void exec() override
    {
        printf("Do copy...\n");
    }
};

class Move : public Command
{
public:
    virtual void exec() override
    {
        printf("Do move...\n");
    }
};

class ActiveObjectEngine
{
public:
    void addCommand(std::unique_ptr<Command> cmd)
    {
        m_Commands.push_back(std::move(cmd));
    }

    void run()
    {
        while (!m_Commands.empty())
        {
            const std::unique_ptr<Command>& cmd = m_Commands.front();
            cmd->exec();
            m_Commands.pop_front();
        }
    }
private:
    std::list<std::unique_ptr<Command>> m_Commands;
};

int _tmain(int argc, _TCHAR* argv[])
{
    std::unique_ptr<Command> c1(new Copy());
    std::unique_ptr<Command> c2(new Move());

    ActiveObjectEngine engine;

    engine.addCommand(std::move(c1));
    engine.addCommand(std::move(c2));

    engine.run();

    return 0;
}

上面的代码基本分两部分:

1. Command类

2. ActiveObjectEngine类

ActiveObjectEngine里面维护了一个列表,存放所有的Command,在run()函数里面,把每一个命令都运行一遍,然后删除。

那么这么做有什么作用呢?

比如,我们想是想一个SleepCommand总是延迟一定时间后执行。我们先尝试搞一个SleepCopy类:

class SleepCopy : public Command
{
public:
    SleepCopy(ActiveObjectEngine& e, DWORD dwDelay) : m_Engine(e), m_dwStartTime(0), m_dwDelay(dwDelay)
    {}

    SleepCopy(const SleepCopy& cmd) : m_Engine(cmd.m_Engine), m_dwStartTime(cmd.m_dwStartTime), m_dwDelay(cmd.m_dwDelay)
    {
    }

    virtual void exec() override
    {
        if (m_dwStartTime == 0)
        {
            m_dwStartTime = ::GetTickCount();
            std::unique_ptr<Command> newCmd(new SleepCopy(*this));
            m_Engine.addCommand(std::move(newCmd));
        }
        else
        {
            DWORD dwUsed = ::GetTickCount() - m_dwStartTime;
            if (dwUsed >= m_dwDelay)
            {
                printf("Do sleep copy..., delayed: %d ms\n", dwUsed);
            }
            else
            {
                std::unique_ptr<Command> newCmd(new SleepCopy(*this));
                m_Engine.addCommand(std::move(newCmd));
            }
        }
    }
private:
    DWORD m_dwStartTime;
    DWORD m_dwDelay;
    ActiveObjectEngine& m_Engine;
};

这个类比前面两个Command略显复杂。主要思想就是,保存一个起始时间,然后在exec函数里面,来检查一下,如果已经到了延时的时间,那么就触发动作,如果没有,那么就创建一个新的command放到ActiveObject对象里面。这样,ActiveObjectEngine的run函数又会跑一次。直到最终延时时间到,触发动作为止。

其实,我们仔细看一下上面的代码,ActiveObjectEngine就是循环依次调用Command。每次调用完毕,就把对应的command对象从列表里面删除。

如果某个对象需要多次被调用,那么可以在exec函数里面处理一下,比如上面的SleepCopy用到的技巧。反正关键就是,如果想到ActiveObjectEngine再调用一次,那么就往它的列表里面插入一个对象。

从ActiveObjectEngine的角度来看,就是每次调用完对象exec()后,就删除,然后对象的exec()可以自己根据情况处理,如果需要再调用一次,那么就再往ActiveObjectEngine里面增加一个对象(或者重新加入当前对象)。

整个过程都是单线程,从每个Command对象来看,其实是可以实现每次调用只处理一部分工作,然后再把对象加入Engine,等待下一次处理。这就好比是用单线程模拟了多线程环境。每次循环都处理掉一部分工作,直到所有任务完成,Engine也就完成目的了。

ActiveObject模式可以很好的时候命令的轮询工作,然后可以在单线程环境里面实现多线程(多任务)的功能。很古老又很好用的一种思想,很多地方可以使用它。值得好好研究一下。在某些场合有意想不到的效果。起码模拟出来的多线程是运行在单线程环境里面的,这可以减少很多因为多线程环境带来的问题,比如同步。。。

完整代码:

// Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <list>
#include <memory>
#include <windows.h>

class Command
{
public:
    virtual void exec() = 0;
};

class ActiveObjectEngine
{
public:
    void addCommand(std::unique_ptr<Command> cmd)
    {
        m_Commands.push_back(std::move(cmd));
    }

    void run()
    {
        while (!m_Commands.empty())
        {
            const std::unique_ptr<Command>& cmd = m_Commands.front();
            cmd->exec();
            m_Commands.pop_front();
        }
    }
private:
    std::list<std::unique_ptr<Command>> m_Commands;
};

class Copy : public Command
{
public:
    virtual void exec() override
    {
        printf("Do copy..., tick count: %d\n", ::GetTickCount());
    }
};

class Move : public Command
{
public:
    virtual void exec() override
    {
        printf("Do move..., tick count: %d\n", ::GetTickCount());
    }
};

class SleepCopy : public Command
{
public:
    SleepCopy(ActiveObjectEngine& e, DWORD dwDelay) : m_Engine(e), m_dwStartTime(0), m_dwDelay(dwDelay)
    {}

    SleepCopy(const SleepCopy& cmd) : m_Engine(cmd.m_Engine), m_dwStartTime(cmd.m_dwStartTime), m_dwDelay(cmd.m_dwDelay)
    {
    }

    virtual void exec() override
    {
        if (m_dwStartTime == 0)
        {
            m_dwStartTime = ::GetTickCount();
            std::unique_ptr<Command> newCmd(new SleepCopy(*this));
            m_Engine.addCommand(std::move(newCmd));
        }
        else
        {
            DWORD dwUsed = ::GetTickCount() - m_dwStartTime;
            if (dwUsed >= m_dwDelay)
            {
                printf("Do sleep copy..., delayed: %d ms\n", dwUsed);
            }
            else
            {
                std::unique_ptr<Command> newCmd(new SleepCopy(*this));
                m_Engine.addCommand(std::move(newCmd));
            }
        }
    }
private:
    DWORD m_dwStartTime;
    DWORD m_dwDelay;
    ActiveObjectEngine& m_Engine;
};

int _tmain(int argc, _TCHAR* argv[])
{
    ActiveObjectEngine engine;

    std::unique_ptr<Command> c1(new Copy());
    std::unique_ptr<Command> c2(new Move());
    std::unique_ptr<Command> c3(new SleepCopy(engine, 5000));

    engine.addCommand(std::move(c1));
    engine.addCommand(std::move(c2));
    engine.addCommand(std::move(c3));

    engine.run();

	return 0;
}
时间: 2024-08-13 14:25:01

Active Object模式的相关文章

Java多线程编程模式实战指南(一):Active Object模式--转载

本文由黄文海首次发布在infoq中文站上:http://www.infoq.com/cn/articles/Java-multithreaded-programming-mode-active-object-part1 .转载请注明作者: 黄文海 出处:http://viscent.iteye.com. Active Object模式简介 Active Object模式是一种异步编程模式.它通过对方法的调用与方法的执行进行解耦来提高并发性.若以任务的概念来说,Active Object模式的核心

Java多线程编程模式实战指南一:Active Object模式(上)

Active Object模式简介 Active Object模式是一种异步编程模式.它通过对方法的调用与方法的执行进行解耦来提高并发性.若以任务的概念来说,Active Object模式的核心则是它允许任务的提交(相当于对异步方法的调用)和任务的执行(相当于异步方法的真正执行)分离.这有点类似于System.gc()这个方法:客户端代码调用完gc()后,一个进行垃圾回收的任务被提交,但此时JVM并不一定进行了垃圾回收,而可能是在gc()方法调用返回后的某段时间才开始执行任务--回收垃圾.我们知

Java多线程编程模式实战指南一:Active Object模式(下)

Active Object模式的评价与实现考量 Active Object模式通过将方法的调用与执行分离,实现了异步编程.有利于提高并发性,从而提高系统的吞吐率. Active Object模式还有个好处是它可以将任务(MethodRequest)的提交(调用异步方法)和任务的执行策略(Execution Policy)分离.任务的执行策略被封装在Scheduler的实现类之内,因此它对外是不"可见"的,一旦需要变动也不会影响其它代码,降低了系统的耦合性.任务的执行策略可以反映以下一些

敏捷软件开发(3)---COMMAND 模式 &amp; Active Object 模式

COMMAND 模式 command模式非常简单,简单到你无法想象的地方. public interface Command { void execute(); } 这就是一个command模式的样子.也许你会觉得,这有点多此一举吗.但是当你使用他的时候,command模式就会闪现光华. 这样一个场景:经理张三叫leader王二去开发一个项目, 王二就安排李四 去开发这个功能A. 李四何时执行,怎么执行就是他自己的事情了. UML图如上所示: 代码如下: public interface Com

java Active Object模式(下)

Active Object模式的评价与实现考量 Active Object模式通过将方法的调用与执行分离,实现了异步编程.有利于提高并发性,从而提高系统的吞吐率. Active Object模式还有个好处是它可以将任务(MethodRequest)的提交(调用异步方法)和任务的执行策略(Execution Policy)分离.任务的执行策略被封装在Scheduler的实现类之内,因此它对外是不“可见”的,一旦需要变动也不会影响其它代码,降低了系统的耦合性.任务的执行策略可以反映以下一些问题: 采

Java多线程编程模式实战指南:Active Object模式(下)

Active Object模式的评价与实现考量 Active Object模式通过将方法的调用与执行分离,实现了异步编程.有利于提高并发性,从而提高系统的吞吐率. Active Object模式还有个好处是它可以将任务(MethodRequest)的提交(调用异步方法)和任务的执行策略(Execution Policy)分离.任务的执行策略被封装在Scheduler的实现类之内,因此它对外是不“可见”的,一旦需要变动也不会影响其它代码,降低了系统的耦合性.任务的执行策略可以反映以下一些问题: 采

java Active Object模式(上)

Active Object模式简介 Active Object模式是一种异步编程模式.它通过对方法的调用与方法的执行进行解耦来提高并发性.若以任务的概念来说,Active Object模式的核心则是它允许任务的提交(相当于对异步方法的调用)和任务的执行(相当于异步方法的真正执行)分离.这有点类似于System.gc()这个方法:客户端代码调用完gc()后,一个进行垃圾回收的任务被提交,但此时JVM并不一定进行了垃圾回收,而可能是在gc()方法调用返回后的某段时间才开始执行任务——回收垃圾.我们知

多线程设计模式:第六篇 - ThreadLocal和Active Object模式

一,ThreadLocal Java 中的 ThreadLocal 类给多线程编程提供了一种可以让每个线程具有自己独立空间的机制,在这个空间内存储的数据是线程特有的,不对外共享. ThreadLocal 类提供了 set() 和 get() 方法用于设置和获取线程特有数据,且 ThreadLocal 支持泛型,这样可以通过参数来指定要存储数据的类型. 二,Active Object模式 Active Object模式的主要目的是实现方法调用和执行分离到不同的线程中,这样可以提高调用方的响应速度,

java 实现Active Object思想

我们一直在说并发编程,我们只知道JDK5有个并发编程包帮我们封装好了多线程下的复杂处理机制,这篇文章的重点不是说它的底层实现原理,只想说下并发包的编程模式思想,我以前一直在想这种思想来源于哪里,面向对象编程的好处应该就是能总结一种模式,只有定义了模式理解了模式,我们平常才能更好的理解一些复杂的编程,这就是抽象到理论的过程吧!我们的前辈把这些编程思想作为一种理论抽象成模式的概念,不就是方便我们更好的理解和接受编程的思想吗?不仅如此,在现在开源如火如荼的进行中,我们怎么通过代码来交流?我们怎么来更好