前言
由于上一篇博客备忘录模式提到了命令模式,所以跳过接下来的4章,直接进入到命令模式的学习~
命令模式
英文:Command
这个名字是不是很熟悉?
what
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作。
场景
宿舍有人过生日,所以预定了一个饭店。我们需要点餐,服务员(接口)进行记录,当点到熊掌鲍鱼时,服务员答道:今天没有这道菜,请点其他菜品~(else语句,没货进行回绝),然后我们点好了,服务员告诉了厨师,并对账目进行了汇总(记录账单),这时候有个朋友要去一份沙拉(取消订单),加一份大盘鸡,我们又叫来了服务员,服务员将账单改好(设置订单)后又通知了厨师去做(执行)
优点
- 容易设计一个命令队列
- 容易将命令记入日志
- 允许接收请求的一方决定是否否决请求
- 容易实现对请求的撤销喝重做
- 由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易
- 把请求一个操作的对象与知道怎么执行一个操作的对象分割开
注意
敏捷开发原则告诉我们,不要为代码添加基于猜测的,实际不需要的功能,如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要(如撤销,恢复)等功能时,把原来的代码重构为命令模式才有意义。
错误解决
可访问性不一致
解决:
原因:返回参数的访问级别小于函数的访问级别,也就是说当定义一个返回参数的方法的时候,如果返回参数的访问级别低于方法的访问级别就会出现这样的错误,比如private,public,protect等。
错误代码:
class Barbecuer
正确代码:
public class Barbecuer
代码展示
烤肉串者(厨师):
public class Barbecuer
{
//烤羊肉串
public void BakeMutton()
{
Console.WriteLine("烤羊肉串,好吃不贵!");
}
//烤鸡
public void BakeChicken()
{
Console.WriteLine("烤鸡,好吃不贵!");
}
}
抽象命令类:
public abstract class Command
{
protected Barbecuer receiver;
//抽象命令类,只需确定“烤肉串者”是谁即可
public Command(Barbecuer receiver)
{
this.receiver = receiver;
}
//执行命令
abstract public void ExcuteCommand();
}
服务员类:(命令者接口)
//服务员类,不用管用户想要什么,反正是命令,只管记录订单,然后通知烤肉者执行即可。
public class Waiter
{
private Command command;
//设置订单
public void SetOrder(Command command)
{
this.command = command;
}
//通知执行
public void Notify()
{
command.ExcuteCommand();
}
}
具体命令类:
//具体命令类:
//烤羊肉串类
class BakeMuttonCommand:Command
{
public BakeMuttonCommand(Barbecuer receiver)
: base(receiver)
{
}
//重写方法,具体命令类,执行命令时,执行具体行为
public override void ExcuteCommand()
{
receiver.BakeMutton();
}
}
//烤鸡类
class BakeChickenCommand : Command
{
public BakeChickenCommand(Barbecuer receiver)
: base(receiver)
{
}
public override void ExcuteCommand()
{
receiver.BakeChicken();
}
}
客户端代码:
class Program
{
static void Main(string[] args)
{
//开店前准备
Barbecuer monkey = new Barbecuer();
Command bakeMuttonCommand1 = new BakeMuttonCommand(monkey);
Command bakeMuttonCommand2 = new BakeMuttonCommand(monkey);
Command bakeChickenCommand1 = new BakeChickenCommand(monkey);
Waiter mm = new Waiter();
//开门营业,服务员根据用户要求,通知厨房开始制作
mm.SetOrder(bakeMuttonCommand1);
mm.Notify(); //调用通知
mm.SetOrder(bakeMuttonCommand2);
mm.Notify();
mm.SetOrder(bakeChickenCommand1);
mm.Notify();
Console.Read();
}
}
效果展示:
后记
本来是很简单的一个模式,但是由于大小写等一些问题,找了半天的解决方案,不过最终的成就感显得更高一些~