命令模式——“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其它对象。命令模式也支持可撤消的操作。(摘自《Head First Design Patterns》)
以下是自已用VS画了一个简图:
创建命令接口:
interface ICommand
{
void Execute();
void Undo();
}
实现三个命令:
class AttackCommand : ICommand
{
#region Command 成员
public void Execute()
{
Console.WriteLine("攻击");
}
public void Undo()
{
Console.WriteLine("撤消攻击");
}
#endregion
}
class RetreatCommand : ICommand
{
#region Command 成员
public void Execute()
{
Console.WriteLine("撤退");
}
public void Undo()
{
Console.WriteLine("撤消撤退");
}
#endregion
}
class NoCommand : ICommand
{
#region ICommand 成员
public void Execute()
{
}
public void Undo()
{
}
#endregion
}
其中空命令为了初始化使用,不必判断NULL了。创建一个司令官,用来发布命令:
class Commander
{
private ICommand UndoCommand = new NoCommand();
public void SetCommand(ICommand command)
{
command.Execute();
UndoCommand = command;
}
public void UndoLastCommand()
{
UndoCommand.Undo();
UndoCommand = new NoCommand();
}
}
测试一下:
Commander commander = new Commander();
AttackCommand attackCommand = new AttackCommand();
RetreatCommand retreatCommand = new RetreatCommand();
commander.SetCommand(attackCommand);
commander.UndoLastCommand();
commander.SetCommand(retreatCommand);
commander.UndoLastCommand();
commander.SetCommand(attackCommand);
commander.SetCommand(retreatCommand);
commander.UndoLastCommand();
commander.UndoLastCommand();//程序只实了一次撤消,因此这里的第二次撤消没有作用,用户可以创建撤消命令数组来存储实现多次撤消。
输出结果:
攻击
撤消攻击
撤退
撤消撤退
攻击
撤退
撤消撤退
在以前的观察者模式中,使用了发布命令,但是没用应用命令模式,现在结合命令模式重新改写一下以前的观察者模式:
下面是用VS画的一个简图:
其中原本用的接口改成了抽象类,为了简化一下代码,这里主要是为了我自己的这个例子。
/// <summary>
/// 主题对象接口
/// </summary>
public interface ISubject
{
List<Observer> Observers
{
get;
set;
}
void RegisterObserver(Observer observer);
void RemoveObserver(Observer observer);
void NotifyObservers();
}
/// <summary>
/// 观察者基类
/// </summary>
public abstract class Observer
{
public abstract void Update(Command command);
#region = Name =
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
#endregion
#region = AttackSlogan =
private string _attackslogan;
public string AttackSlogan
{
get { return _attackslogan; }
set { _attackslogan = value; }
}
#endregion
#region = RetreatSlogan =
private string _retreatslogan;
public string RetreatSlogan
{
get { return _retreatslogan; }
set { _retreatslogan = value; }
}
#endregion
}
/// <summary>
/// 斧头小队--观察者
/// </summary>
public class AxeTeam : Observer
{
#region Observer 成员
public AxeTeam()
{
this.Name = "斧头小队";
this.AttackSlogan = "用斧头攻击,势死如归!";
this.RetreatSlogan = "坚守阵地,死也不放弃!";
}
public override void Update(Command command)
{
command.Observer = this;
command.Execute();
}
#endregion
}
/// <summary>
/// 弓箭手小队--观察者
/// </summary>
public class BowAndArrowTeam : Observer
{
#region Observer 成员
public BowAndArrowTeam()
{
this.Name = "弓箭手小队";
this.AttackSlogan = "弓箭手掩护,退后十步,射箭!";
this.RetreatSlogan = "边撤退,边掩护斧头小队!";
}
public override void Update(Command command)
{
command.Observer = this;
command.Execute();
}
#endregion
}
/// <summary>
/// 匕首小队--观察者
/// </summary>
public class KnifeTeam : Observer
{
#region Observer 成员
public KnifeTeam()
{
this.Name = "匕首小队";
this.AttackSlogan = "匕首攻击,打不过就跑!";
this.RetreatSlogan = "快撤啊,我军大势已去!";
}
public override void Update(Command command)
{
command.Observer = this;
command.Execute();
}
#endregion
}
/// <summary>
/// 司令官---主题对象以及发布命令
/// </summary>
public class Commander : ISubject
{
#region ISubject 成员
private List<Observer> _observers;
public List<Observer> Observers
{
get
{
return _observers;
}
set
{
_observers = value;
}
}
public Command Command = new NoCommand();
public Commander()
{
_observers = new List<Observer>();
}
public void RegisterObserver(Observer observer)
{
this.Observers.Add(observer);
}
public void RemoveObserver(Observer observer)
{
this.Observers.Remove(observer);
}
public void NotifyObservers()
{
foreach (Observer observer in this.Observers)
{
observer.Update(this.Command);
}
}
#endregion
public void SetCommand(Command command)
{
this.Command = command;
NotifyObservers();
}
}
/// <summary>
/// 命令基类
/// </summary>
public abstract class Command
{
#region = Observer =
private Observer _observer;
public Observer Observer
{
get { return _observer; }
set { _observer = value; }
}
#endregion
public abstract void Execute();
}
/// <summary>
/// 攻击命令
/// </summary>
class AttackCommand : Command
{
#region Command 成员
public override void Execute()
{
Console.WriteLine(string.Format("{0}:{1}", this.Observer.Name, this.Observer.AttackSlogan));
}
#endregion
}
/// <summary>
/// 撤退命令
/// </summary>
class RetreatCommand : Command
{
#region Command 成员
public override void Execute()
{
Console.WriteLine(string.Format("{0}:{1}", this.Observer.Name, this.Observer.RetreatSlogan));
}
#endregion
}
/// <summary>
/// 空命令
/// </summary>
class NoCommand : Command
{
#region Command 成员
public override void Execute()
{
}
#endregion
}
测试一下:
//实例化司令官和三个小队
Commander commander = new Commander();
AxeTeam axe = new AxeTeam();
BowAndArrowTeam baa = new BowAndArrowTeam();
KnifeTeam knife = new KnifeTeam();
AttackCommand attackCommand = new AttackCommand();
RetreatCommand retreatCommand = new RetreatCommand();
//注册观察者
commander.RegisterObserver(axe);
commander.RegisterObserver(baa);
commander.RegisterObserver(knife);
//司令官下命令
commander.SetCommand(attackCommand);
commander.SetCommand(retreatCommand);
//匕首小队怕死,从军队中删除
Console.WriteLine("匕首小队怕死,从军队中删除");
commander.RemoveObserver(knife);
//司令官再次下命令
commander.SetCommand(attackCommand);
commander.SetCommand(retreatCommand);
观察者模式和命令模式已经结到一起,输出结果:
斧头小队:用斧头攻击,势死如归!
弓箭手小队:弓箭手掩护,退后十步,射箭!
匕首小队:匕首攻击,打不过就跑!
斧头小队:坚守阵地,死也不放弃!
弓箭手小队:边撤退,边掩护斧头小队!
匕首小队:快撤啊,我军大势已去!
匕首小队怕死,从军队中删除
斧头小队:用斧头攻击,势死如归!
弓箭手小队:弓箭手掩护,退后十步,射箭!
斧头小队:坚守阵地,死也不放弃!
弓箭手小队:边撤退,边掩护斧头小队! ------------------------- 至此,全部介结完毕,有错误之处还请大家指出。