模式介绍
命令模式将请求封装为对象,从而允许开发人员根据接收到该命令的类来不同地对待该请求。此外,它能够实现更复杂的体系结构,甚至可以实现诸如撤销/重做之类的操作。
责任链模式非常适合命令模式,因为前者可以使用后者的对象来表示其请求。
示例
我们将建模一个系统,在该系统中,我们可以在快餐店创建订单,并使用命令模式进行订单添加、删除和修改。
菜单:
/// <summary>
/// Represents an item being ordered from this restaurant.
/// </summary>
public class MenuItem
{
public string Name { get; set; }
public int Amount { get; set; }
public double Price { get; set; }
public MenuItem(string name, int amount, double price)
{
Name = name;
Amount = amount;
Price = price;
}
public void Display()
{
Console.WriteLine("
Name: " + Name);
Console.WriteLine("Amount: " + Amount.ToString());
Console.WriteLine("Price: $" + Price.ToString());
}
}
顾客:
/// <summary>
/// The Invoker class
/// </summary>
public class Patron
{
private OrderCommand _orderCommand;
private MenuItem _menuItem;
private FastFoodOrder _order;
public Patron()
{
_order = new FastFoodOrder();
}
public void SetCommand(int commandOption)
{
_orderCommand = new CommandFactory().GetCommand(commandOption);
}
public void SetMenuItem(MenuItem item)
{
_menuItem = item;
}
public void ExecuteCommand()
{
_order.ExecuteCommand(_orderCommand, _menuItem);
}
public void ShowCurrentOrder()
{
_order.ShowCurrentItems();
}
}
public class CommandFactory
{
//Factory method
public OrderCommand GetCommand(int commandOption)
{
switch (commandOption)
{
case 1:
return new AddCommand();
case 2:
return new ModifyCommand();
case 3:
return new RemoveCommand();
default:
return new AddCommand();
}
}
}
抽象的命令类:
/// <summary>
/// The Command abstract class
/// </summary>
public abstract class OrderCommand
{
public abstract void Execute(List<MenuItem> order, MenuItem newItem);
}
具体的命令类:
/// <summary>
/// A concrete command
/// </summary>
public class AddCommand : OrderCommand
{
public override void Execute(List<MenuItem> currentItems, MenuItem newItem)
{
currentItems.Add(newItem);
}
}
/// <summary>
/// A concrete command
/// </summary>
public class RemoveCommand : OrderCommand
{
public override void Execute(List<MenuItem> currentItems, MenuItem newItem)
{
currentItems.Remove(currentItems.Where(x=>x.Name == newItem.Name).First());
}
}
/// <summary>
/// A concrete command
/// </summary>
public class ModifyCommand : OrderCommand
{
public override void Execute(List<MenuItem> currentItems, MenuItem newItem)
{
var item = currentItems.Where(x => x.Name == newItem.Name).First();
item.Price = newItem.Price;
item.Amount = newItem.Amount;
}
}
客户端调用:
static void Main(string[] args)
{
Patron patron = new Patron();
patron.SetCommand(1 /*Add*/);
patron.SetMenuItem(new MenuItem("French Fries", 2, 1.99));
patron.ExecuteCommand();
patron.SetCommand(1 /*Add*/);
patron.SetMenuItem(new MenuItem("Hamburger", 2, 2.59));
patron.ExecuteCommand();
patron.SetCommand(1 /*Add*/);
patron.SetMenuItem(new MenuItem("Drink", 2, 1.19));
patron.ExecuteCommand();
patron.ShowCurrentOrder();
//Remove the french fries
patron.SetCommand(3 /*Remove*/);
patron.SetMenuItem(new MenuItem("French Fries", 2, 1.99));
patron.ExecuteCommand();
patron.ShowCurrentOrder();
//Now we want 4 hamburgers rather than 2
patron.SetCommand(2 /*Edit*/);
patron.SetMenuItem(new MenuItem("Hamburger", 4, 2.59));
patron.ExecuteCommand();
patron.ShowCurrentOrder();
Console.ReadKey();
}
总结
命令设计模式试图将命令封装为对象,并允许不同的接收器根据接收器自己的设计来处理它们。
源代码
https://github.com/exceptionnotfound/DesignPatterns/tree/master/Command
原文
https://www.exceptionnotfound.net/command-the-daily-design-pattern/