设计模式(10)---命令模式

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

一、引言:

路边有一个烤肉摊,有一位老板负责给客人烧烤食物。如果客人很少,老板都能准确记住大家的要求,随着客人的增多,要求越来越多,老板很难满足大家要求,老板应该怎么办?

首先说明为什么客人多了,老板满足不了大家的要求,因为“用程序猿的话说是因为:紧耦合”。松耦合就能很好的解决此问题,也就是本文介绍的命令模式。先给出紧耦合代码:

classPRogram

{staticvoidMain(string[] args)

{

Receiver receiver=newReceiver();

receiver.BakeChickenWing();

Console.Read();

}

}publicclassReceiver//boss{publicvoidBakeMutton()

{

Console.WriteLine("bake mutton");

}publicvoidBakeChickenWing()

{

Console.WriteLine("bake chickenwing");

}

}

View Code

二、定义:

命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销操作。

解释:将请求命令封装为一个对象,并用日志记录下来,其中它支持命令撤销功能。

三、UML图及基本代码:

基本代码:

classReceicer

{publicvoidAction()

{

Console.WriteLine("执行请求");

}

}abstractclassCommand

{protectedReceicer receiver;publicCommand(Receicer receiver)

{this.receiver =receiver;

}abstractpublicvoidExecute();

}classConcreteCommand : Command

{publicConcreteCommand(Receicer receiver)

:base(receiver)

{ }publicoverridevoidExecute()

{

receiver.Action();

}

}classInvoker

{privateCommand command;publicvoidSetCommand(Command command)

{this.command =command;

}publicvoidExecuteCommand()

{

command.Execute();

}

}

调用:

Receicer receiver =newReceicer();

Command command=newConcreteCommand(receiver);

Invoker invoker=newInvoker();

invoker.SetCommand(command);

invoker.ExecuteCommand();

解释:映射客人到酒店就餐。Receiver是命令的接收者,相当于酒店中的大厨;Command命令抽象类,ConcreteCommand是具体的命令,相当于点菜请求,命令中应该包含命令的接收者。Invoke是命令的传达者,相当于酒店的服务员,负责记录客人点菜请求,并传达给后厨。

四、举例说明:

学校高一学生进行军训,校长发布让学生跑10000米的命令。整个过程:校长发布命令给军训教官,教官传达校长命令给学生,学生接收到命令后执行相应的操作。在下面实例中,Receiver是学生,操作跑10000米的命令。Command是命令,必需知道命令的接收者。Drillmaster是教官,教官必需知道命令是什么,并传达命令。

//校长发布学生跑1000米的命令,教官传达此命令给学生,学生是命令的接收者//客户端:校长,命令的发出者必须知道具体的命令、接受者、传达命令者classProgram

{staticvoidMain(string[] args)

{

Receiver receiver=newReceiver();

Command command=newConcreteCommand(receiver);

Drillmaster drillmaster=newDrillmaster(command);

drillmaster.ExecuteCommand();

Console.Read();

}

}//命令接收者publicclassReceiver

{publicvoidRun1000Meters()

{

Console.WriteLine("跑10000米");

}

}//抽象命令publicabstractclassCommand

{protectedReceiver receiver;publicCommand(Receiver receiver)

{this.receiver =receiver;

}publicabstractvoidAction();

}//具体的命令,必须知道命令接受者publicclassConcreteCommand : Command

{publicConcreteCommand(Receiver receiver)

:base(receiver)

{ }publicoverridevoidAction()

{

receiver.Run1000Meters();

}

}//教官:命令的传达者,负责调用命令对象的方法来保证命令执行publicclassDrillmaster

{publicCommand command;publicDrillmaster(Command command)

{this.command =command;

}publicvoidExecuteCommand()

{

command.Action();

}

}

View Code

五、解决引言中的问题

客人点菜命令的接收者,老板(大厨):

publicclassReceiver

{publicvoidBakeMutton()

{

Console.WriteLine("bake mutton");

}publicvoidBakeChickenWing()

{

Console.WriteLine("bake chickenwing");

}

}

点菜命令:

publicabstractclassCommand

{protectedReceiver receiver;publicCommand(Receiver receiver)

{this.receiver =receiver;

}abstractpublicvoidExecute();

}classConcreteCommand1 : Command

{publicConcreteCommand1(Receiver receiver)

:base(receiver)

{ }publicoverridevoidExecute()

{

receiver.BakeMutton();

}

}classConcreteCommand2 : Command

{publicConcreteCommand2(Receiver receiver)

:base(receiver)

{ }publicoverridevoidExecute()

{

receiver.BakeChickenWing();

}

}

增加一个服务生,负责记录客人点菜命令,并传达给大厨。点菜命令可以进行增加或取消操作。

publicclassInvoker

{privateIList<Command> commands =newList<Command>();publicvoidAddCommand(Command command)

{

commands.Add(command);

Console.WriteLine("增加订单"+command.ToString());

}publicvoidCancelCommand(Command command)

{

commands.Remove(command);

Console.WriteLine("取消订单"+command.ToString());

}publicvoidExecuteCommand()

{foreach(Command commandincommands)

{

command.Execute();

}

}

}

客户端调用:

Receiver receiver =newReceiver();

Command command1=newConcreteCommand1(receiver);

Command command2=newConcreteCommand2(receiver);

Invoker invoker=newInvoker();

invoker.AddCommand(command1);

invoker.AddCommand(command2);

invoker.CancelCommand(command1);

invoker.ExecuteCommand();

六、优缺点及适用场景

优点:

比较容易的设计一个命令队列;在需要的情况下,可以比较容易的将命令计入日志;允许接收请求的一方决定是否要否决请求;比较容易的对命令实现撤销和重做;由于加入新的具体命令类不影响其他的类,因此增加新的具体命令类比较容易。

缺点:

可能会导致系统具有过多的具体命令类。

适用场景:

个人理解:基本上能表现其优点的地方都可以使用命令模式。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航