设计模式--命令模式
概念
将一个请求封装为一个对象,从而使得你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
结构图
角色说明
-
Client
这个就是我们的客户大大了
发布命令者 -
Invoker
调用者
要求该命令执行这个请求(也就是接收命令并执行命令) -
Command
声明执行操作的接口
需要执行的命令在此声明 -
ConcreteCommand
将一个接收者对象绑定一个工作,调用接收者相应的操作,实现execute -
Receiver
接收者,实际做工的角色,我们的命令的执行是由这个角色去做的。
实现
- Command
abstract class Command
{
protected Receiver receiver;
public Command(Receiver receiver)
{
this.receiver = receiver;
}
abstract public void Execute();
}
- ConcreteCommnad
class ConcreteCommnad : Command
{
public ConcreteCommnad(Receiver receiver ):base(receiver)
{ }
public override void Execute()
{
receiver.Action();
}
}
- Invoker
class Invoker
{
private Command command;
public void Setcommand(Command command)
{
this.command = command;
}
public void ExecuteCommand()
{
command.Execute();
}
- Receiver
class Receiver
{
public void Action()
{
Console.WriteLine("执行请求!");
}
}
- 客户端
static void Main(string[] args)
{
Receiver r = new Receiver();
Command c = new ConcreteCommnad(r);
Invoker i = new Invoker();
i.Setcommand(c);
i.ExecuteCommand ();
Console.Read();
}
优点
-
解除类之间的耦合
-
可扩展性好
-
命令模式与其他模式相结合使用更加nice
-
比较容易设计一个命令队列
-
比较容易将命令计入日志
-
允许接收请求的一方决定是否否决请求
-
可以容易的实现对请求的撤销和重做
-
增加新的具体的命令类很容易
如何解除类之间的耦合
例子:
前景描述:
路边单人经营的烧烤店和有服务员的烧烤店
- 单人经营的烧烤店:
烤:
public class Barbecuer
{
//烤肉串
public void BakeMutton()
{
Console.WriteLine("烤肉串");
}
public void BackChickwing()
{
Console.WriteLine("烤鸡翅");
}
}
客户要求:
static void Main(string[] args)
{
Barbecuer boy = new Barbecuer();
boy.BakeMutton();
boy.BakeMutton();
boy.BakeMutton();
boy.BakeMutton();
boy.BakeMutton();
boy.BakeMutton();
boy.BackChickwing();
Console.Read();
}
问题描述:
我们可以发现,客户提出要求和摊主烤肉是 直接通信的关系,那么摊主的职责就比较大啦,他要记住客户分别都要了多少串,还要负责算账,如果其中一个客户要增加或减少串对于摊主来说任务就比较大,容易混淆,且目前的状况是客户与摊主直接沟通,现在两个类是紧耦合的状态。
- 进入服务员
结构图:
抽象命令类:
- 客户端
static void Main(string[] args)
{
//前提装备
Barbecuer boy = new Barbecuer();//烤肉者就位
//烤肉串和烤鸡翅的命令由烤肉工作者具体来做,所以(boy)其实是指明了接收者
//指明接收者的动作
Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);
Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);
Command bakeChickenwingCommand = new BackChickenwingCommand(boy);
Waiter girl = new Waiter();
//营业
girl.SetOrder(bakeMuttonCommand1);
girl.Notify();
girl.SetOrder(bakeMuttonCommand2);
girl.Notify();
girl.SetOrder(bakeChickenwingCommand);
girl.Notify();
Console.Read();
}
- 命令类
public abstract class Command
{
//抽象命令
protected Barbecuer receiver;
public Command (Barbecuer receiver)
{
this.receiver = receiver;
}
//执行命令
abstract public void ExcuteCommand();
}
- 具体命令
class BakeMuttonCommand : Command //烤肉串
{
public BakeMuttonCommand(Barbecuer receiver):base(receiver)
{
}
public override void ExcuteCommand()
{
receiver.BakeMutton ();
}
}
class BackChickenwingCommand : Command
{
public BackChickenwingCommand(Barbecuer receiver) : base(receiver)
{ }
public override void ExcuteCommand()
{
receiver.BackChickwing ();
}
}
- 服务员类
public class Waiter
{
private Command command;
//设置订单
public void SetOrder(Command command)
{
this.command = command;
}
public void Notify()
{
command.ExcuteCommand ();
}
}
可以发现有了 服务员后客人的命令不再直接传给烤肉人员, 而是由服务人员去传递。这样就避免的紧耦合