命令模式:
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可测销的操作。
在软件系统中,行为请求者和行为实现者通常是一种紧耦合的关系,但在某些场合,需要对请求做记录,有撤销等处理时,这种紧耦合就难以处理,需要用到一个接收者(Invoker)。
命令模式组成:
抽象命令角色(Command):定义命令的接口,声明执行的方法;
具体命令角色(ConcreteCommand):继承自抽象命令,将一个接收者对象绑定于一个动作,调用接收者相应的操作,已完成命令。
调用者角色(Invoker):要求命令执行请求,通常会持有很多命令对象。是客户端真正触发命令并要求执行相应操作的对象,也就是和客户端打交道的。
接收者(Receiver):真正执行一个来自Invoker请求的类,任何类都可以作为一个接收者,只要能实现命令要求的相应功能。
命令模式实现代码:
/// 接收者类,知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者。
public class Receiver
{
/// 真正的命令实现
public void Action()
{
System.out.println("Execute request!");
}
}
/// 抽象命令类,用来声明执行操作的接口
public interface ICommand
{
void Execute();
}
/// 具体命令类,实现具体命令。
public class ConcereteCommand extends ICommand
{
// 具体命令类包含有一个接收者,将这个接收者对象绑定于一个动作
private Receiver receiver;
public ConcereteCommand(Receiver receiver)
{
this.receiver = receiver;
}
/// 说这个实现是“虚”的,因为它是通过调用接收者相应的操作来实现Execute的
public void Execute()
{
receiver.Action();
}
}
/// 调度类,要求该命令执行这个请求
public class Invoker
{
private ICommand command;
/// 设置命令
public void SetCommand(ICommand command)
{
this.command = command;
}
/// 执行命令
public void ExecuteCommand()
{
command.Execute();
}
}
// 客户端
static void Main(string[] args)
{
Receiver receiver = new Receiver();
ICommand command = new ConcereteCommand(receiver);
Invoker invoker = new Invoker();
invoker.SetCommand(command);
invoker.ExecuteCommand();
}
现在已去烧烤店吃烧烤为例,店里有服务员,我们把点菜告诉服务员,服务员记录后给烧烤制作者制作。
// 抽象命令类
abstract public class Command {
protected Barbecuer receiver;
public Command(Barbecuer receiver) {
// TODO Auto-generated constructor stub
this.receiver = receiver;
}
abstract public void excuteCommand();
}
// 烤鸡翅命令
public class backChickenWingCommand extends Command {
public backChickenWingCommand(Barbecuer receiver) {
// TODO Auto-generated constructor stub
super(receiver);
}
// 执行命令
@Override
public void excuteCommand() {
// TODO Auto-generated method stub
receiver.bakeChickenWing();
}
}
// 烤羊肉命令
public class bakeMuttonCommand extends Command {
public bakeMuttonCommand(Barbecuer receiver) {
// TODO Auto-generated constructor stub
super(receiver);
}
// 执行命令
@Override
public void excuteCommand() {
// TODO Auto-generated method stub
receiver.bakeMutton();
}
}
// 请求者
import java.util.ArrayList;
public class Waiter {
ArrayList<Command> orders = new ArrayList<>();
// 设置订单
public void setOrder(Command c) {
orders.add(c);
System.out.println("增加订单:" + c.toString());
}
// 取消订单
public void cancelOrder(Command c) {
orders.remove(c);
System.out.println("取消订单:" + c.toString());
}
// 通知全部执行
public void notifyToExec() {
for (Command command : orders) {
command.excuteCommand();
}
}
}
// 客户端
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Barbecuer barbecuer = new Barbecuer();
Command command1 = new bakeMuttonCommand(barbecuer);
Command command2 = new bakeMuttonCommand(barbecuer);
Command command3 = new backChickenWingCommand(barbecuer);
Waiter hotGirl = new Waiter();
hotGirl.setOrder(command1);
hotGirl.setOrder(command2);
hotGirl.setOrder(command3);
hotGirl.notifyToExec();
}
}
输出结果:
增加订单:bakeMuttonCommand@15db9742
增加订单:bakeMuttonCommand@6d06d69c
增加订单:backChickenWingCommand@7852e922
烤羊肉串!
烤羊肉串!
烤鸡翅了!
uml图:
分析:
命令模式优点:
1、可以加入新的命令类而不影响其他的类;
2、容易设计一个命令队列,保存要执行的所有命令;
3、可以较为容易的将命令计入日志;
4、允许请求接收的一方决定是否否决请求;
5、可以较为容易的对请求撤销或重做。