在许多设计中,经常会出现一个对象直接请求另一个对象调用其方法以达到某种目的的行为,这里的两个类之间就会出现紧耦合。这很不好,所以我们应该将 方法的请求者 和 方法的实现者 分开。
比如我们可以直接用手按电视机上的按钮调节音量,这样对我们来说很麻烦,我们可以使用遥控器作为中介,相当于一个命令,这样以后就可以使用电视机遥控器(命令发送者)通过按钮(具体命令)来遥控电视机(命令接收者)。
命令模式包含以下角色:
Command
:声明执行命令的接口;Concrete Command
:抽象命令类的具体实现类;Receiver
:执行命令功能的相关操作;Invoker
:是请求的发送者,通常拥有很多命令对象。package command;
public class CommandPattern
{
public static void main(String[] args)
{
Command cmd=new ConcreteCommand();
Invoker ir=new Invoker(cmd);
System.out.println("客户访问调用者的call()方法...");
ir.call();
}
}
//调用者
class Invoker
{
private Command command;
public Invoker(Command command)
{
this.command=command;
}
public void setCommand(Command command)
{
this.command=command;
}
public void call()
{
System.out.println("调用者执行命令command...");
command.execute();
}
}
//抽象命令
interface Command
{
public abstract void execute();
}
//具体命令
class ConcreteCommand implements Command
{
private Receiver receiver;
ConcreteCommand()
{
receiver=new Receiver();
}
public void execute()
{
receiver.action();
}
}
//接收者
class Receiver
{
public void action()
{
System.out.println("接收者的action()方法被调用...");
}
}
下面再来看一下具体的例子:客户去餐馆吃饭,有肠粉、河粉、混沌,客户向服务员选择以上早餐的几种,服务员将客户的请求交给相关的厨师去做。这里的早餐相当于 命令
,服务员相当于 调用者
,厨师相当于 接收者
。
首先,定义一个早餐类(Breakfast
),它是抽象命令类,有抽象方法 cooking(),说明要做什么;再定义其子类肠粉类(ChangFen
)、馄饨类(HunDun
)和河粉类(HeFen
),它们是具体命令类,实现早餐类的 cooking() 方法,但它们不会具体做,而是交给具体的厨师去做;具体厨师类有肠粉厨师(ChangFenChef
)、馄蚀厨师(HunDunChef
)和河粉厨师(HeFenChef
),他们是命令的接收者;最后,定义服务员类(Waiter
),它接收客户的做菜请求,并发出做菜的命令。客户类是通过服务员类来点菜的。
具体的代码就不写了,上面的例子主要是想让读者理解命令和实现者之间的关系。
优点如下:
缺点是:可能产生大量的具体命令类,增加系统的复杂性。