【转】设计模式学习笔记(14)-命令
命令(Command)模式是一个比较有意思的模式,如果我们要操作一个对象,我们需要指定一个对该对象的应用,然后调用该对象的某一方法,这是比较常用的方法。而命令模式则是将一个命令包装成一个对象,然后在该对象上指定一个接受者,然后把命令往系统里一扔,然后就与我无关了,至于系统该怎么调用那是系统的事。这有点类似于大炮和导弹的区别。如果我们用大炮摧毁一个目标时,我们会进行计算,瞄准目标然后击中;而导弹则不同,将目标信息输入导弹后我这边就不管了,因为导弹有了目标的充足信息,它完全可以自己找到目标。命令模式就类似于导弹的这种方式。
命令模式的好处还是解耦。发送者和接受者没有明显的耦合关系,发送者只知道接受者的名字而已而接受者则一无所知,接受者依赖系统的某一个部分调用其方法而发送者也依赖于该部分,这将依赖倒置(DI)过来从而达到了降低耦合的目的。
Command是所有命令的接口,里面只有一个Execute方法,ConcreteCommand是一个实现,Receiver是接受者,Invoker是调Command的类。具体流程是这样的,Client构造了一个Command对象,在里面指定了接受者即Receiver,Client将该Command对象提交给系统,然后在某个条件下系统的Invoker(可以理解为专门处理Command的类)调用该Command方法,这样Client达到了间接访问Receiver的方法。
这里有一个具体的代码实现:
class Receiver
{
public:
void Action() {
cout << "An action invoked!" << endl;
}
};
这是Receiver类,往往与具体操作绑定
class Command
{
protected:
Command(){}
public:
virtual void Execute() = 0;
};
定义Command接口,只有一个Execute方法
class ConcreteCommand : public Command
{
private:
Receiver* _receiver;
public:
ConcreteCommand(Receiver* receiver) : _receiver(receiver){}
void Execute() {
_receiver->Action();
}
};
ConcreteCommand Command接口的具体实现
class Invoker
{
public:
void invoke(Command* command) {
command->Execute();
}
};
系统负责执行各种Command的类,它由系统创建,一般只有一个实例(单例模式)。
Invoker* invoker = new Invoker(); Command* command = new ConcreteCommand(new Receiver()); invoker->invoke(command);
主方法,定义了invoker和command
最终输出结果是
An action invoked!
由于我们这个程序比较小,所以Invoker和command放在一起了,一般情况下是不在一起的,并且Invoker是不可见的,所以这种模式符合隐式调用(Implicit Invocation)风格,而这种风格能极大地减少耦合。
我们上面的例子一个Command只执行了一个操作,而实际上我们可以定义一个MacroCommand(宏命令),它可以执行一系列操作,这样由类似于Facade模式:将一系列操作组合起来,为外界提供简单的接口。
最后来看看Command模式的适用性:
- 你需要抽象出待执行的动作以参数化某对象以达到类似于回调(Callback)的参数化机制
- 在不同的时刻指定、排列和执行请求
- 支持取消操作
- 支持修改日志
- 支持事务操作
其实上面的Invoker在实际中往往是从命令队列中取得命令的,这样就可以对命令有所取舍。Command模式是实现取消功能的关键,每次的Command可以通过栈存储结构存储,如果要取消则可以调用以往操作的逆操作。而事务则可以通过将Command分组,这样可以达到同时执行的目的。
原文:http://lecoding.com/articles/232.html
posted on 2013-03-05 16:09 TheKingOfKingFish 阅读(167) 评论(0) 收藏 举报

浙公网安备 33010602011771号