1. 概述
Composite Pattern是一种非常优雅的模式,实际使用中出现频率相当高。其通过对请求进行封装,解除了请求的发布者和具体实现者之间的耦合关系。
类图:
Customer:命令的发布者
Command:命令的接口
Concreate_command:具体命令的实现
Worker:命令的具体执行者
2. 实例
一个顾客跑到餐馆吃饭,他告诉服务员需要点的菜,服务员整理顾客的需要,然后告诉厨师,厨师负责具体做菜
对应上面的类图
Customer:顾客
Concrete_command:服务员
Worker:厨师
顾客和厨师解耦,顾客不需要关心具体哪个厨师在给他做菜,这就是command模式的好处之一。
实现代码如下:
#include <iostream>
using namespace std;
//厨师,具体的worker
class Cooker
{
public:
void Do()
{
cout << "cooker cook" << endl;
};
};
//command接口
class Command
{
public:
virtual ~Command()
{
}
virtual void Do() = 0;
};
//concrete_command
class Waiter: public Command
{
public:
Waiter(Cooker* cooker)
{
_cooker = cooker;
}
virtual void Do()
{
_cooker->Do();
}
private:
//命令的执行者
Cooker* _cooker;
};
//命令的发起者
class Customer
{
public:
Customer(Command* command)
{
_command = command;
}
void order()
{
cout << "customer order" << endl;
_command->Do();
}
private:
Command* _command;
};
int main()
{
//命令的执行者
Cooker cooker;
//命令的封装
Command* command = new Waiter(&cooker);
//命令的发起者
Customer customer(command);
//执行命令
customer.order();
if(command)
{
delete command;
}
return 0;
}
输出:
$ ./bin/test
customer order
cooker cook
3. undo
do操作完成了客户的需要,而undo操作则需要表示客户“后悔了”。undo操作使用非常多,常用的软件里面基本上都有undo的实现,使用undo,只要在command命令增加undo的接口,同时,concrete_command需要保存do之前的状态。
提供给客户取消订单的操作。
代码:
#include <iostream>
using namespace std;
class Cooker
{
public:
Cooker()
{
_value = 0;
}
void Do()
{
_value++;
cout << "cooker do" << endl;
};
//标记值
void value()
{
cout << "value=" << _value << endl;
};
private:
int _value;
};
class Command
{
public:
virtual ~Command()
{
}
virtual void Do() = 0;
virtual void unDo() = 0;
};
class Waiter: public Command
{
public:
Waiter(Cooker* cooker)
{
_cooker = cooker;
_bak_cooker = new Cooker;
}
~Waiter()
{
if(_bak_cooker)
{
delete _bak_cooker;
_bak_cooker = NULL;
}
}
virtual void Do()
{
cout << "waiter do" << endl;
//保留状态
*_bak_cooker = *_cooker;
_cooker->Do();
}
//取消操作
virtual void unDo()
{
cout << "waiter undo" << endl;
//恢复状态
*_cooker = *_bak_cooker;
}
private:
Cooker* _cooker;
Cooker* _bak_cooker;
};
class Customer
{
public:
Customer(Command* command)
{
_command = command;
}
void order()
{
cout << "customer order" << endl;
_command->Do();
}
void unDo()
{
cout << "customer cancel rder" << endl;
_command->unDo();
}
private:
Command* _command;
};
int main()
{
Cooker cooker;
Command* command = new Waiter(&cooker);
Customer customer(command);
customer.order();
cooker.value();
customer.unDo();
cooker.value();
if(command)
{
delete command;
}
return 0;
}
输出:
$ ./bin/test
customer order
waiter do
cooker do
value=1
customer cancel rder
waiter undo
value=0