Command模式属于行为模式,作为大名鼎鼎的23个设计模式之一,Command模式理解起来不如工厂模式,单例模式等那么简单直白。究其原因,行为模式着重于使用,如果没有编程实践,确实不如创造模式那么直白。我们先看看UML类图。

估计很多同学看着图就晕了,那么多东西,Command和Concrete Command还好理解,那些Receiver和Invoker又是什么东西呢?

 

别着急,只要理解了一点,这个模式就很容易理解了,下面划重点,Command模式最主要的特点,是将命令封装成类,在类中保存命令执行的上下文(即该命令执行的参数,执行的对象),以实现命令执行对象和命令发出对象的解耦

 

这样一来是不是觉得好理解多了?Command类里面的Receiver,就是命令具体执行的对象。这里的Client可以理解为装配环境,在这里面代码实例化Command。Invoker内部保存命令(可以保存多条命令,实现命令记录查看,撤销等),客户端代码通过Invoker来操作命令。接下来我们看看示例代码。

 

定义Command接口

首先我们定义一个支持撤销的Command接口。

    interface Command
{
void Execute();
void Undo();
}

定义Receiver

接下来我们定义Receiver,也就是命令的执行对象,这里我们定义一个Ball类。

    class Ball
{
public int Size { get; set; } = 10;
public string Name { get; set; } = "My First Ball";
public void Inspect()
{
Console.WriteLine("My Name is {0} and size is {1}", Name, Size);
}
}

定义具体命令

这里定义两个命令,一个修改名字,一个修改大小。

    class ChangeNameCommand : Command
{
private Ball _Ball;
private string _OldName;
public string NameYouWant { get; set; }
public ChangeNameCommand(Ball ball)
{
_Ball = ball;
} public void Execute()
{
_OldName = _Ball.Name;
_Ball.Name = NameYouWant;
} public void Undo()
{
_Ball.Name = _OldName;
}
} class ChangeSizeCommand : Command
{
//代码大同小异,略
}

定义Invoker

接下来是Invoker,,也就是存储命令,并最终会被用户代码调用的类,这里我们叫它CommandManager。

    class CommandManager
{
private Stack<Command> commands = new Stack<Command>(); public void RunCommand(Command command)
{
command.Execute();
commands.Push(command);
} public void Undo()
{
if (commands.Count > 0)
{
var command = commands.Pop();
command.Undo();
}
} public void ShowCommands()
{
var temp = commands.Reverse();
foreach(var command in temp)
{
//display command
}
}
}

使用命令

现在我们看看客户端代码是怎么使用他们的,定义Ball,定义命令,通过CommandManager去调用,这样可以方便查看命令记录,撤销命令,等。

        static void Main(string[] args)
{
Ball ball = new Ball();
ball.Inspect(); ChangeNameCommand changeName = new ChangeNameCommand(ball) { NameYouWant = "Changed" };
ChangeSizeCommand changeSize = new ChangeSizeCommand(ball) { SizeYouWant = 20 }; CommandManager manager = new CommandManager();
manager.RunCommand(changeName);
manager.RunCommand(changeSize);
ball.Inspect(); manager.ShowCommands(); manager.Undo();
ball.Inspect(); manager.Undo();
ball.Inspect();
}

就酱,我们已经实现了命令模式,并且还支持命令的记录与撤销,希望能对大家有点帮助。

最新文章

  1. js创建对象的高级模式
  2. liunx下,只获取主机的IP?
  3. Java中的闪光点:ThreadLocal是线程Thead的局部变量,可替代同步机制的设计,值得学习和研究
  4. Yocto开发笔记之《工具使用:TFTP &amp; NFS &amp; SSH》(QQ交流群:519230208)
  5. [转]GPS纠偏算法,适用于google,高德体系的地图
  6. Asp.net中从后台中如何获取html控件
  7. java poi导入EXCEL xls文件代码
  8. [HDOJ3367]Pseudoforest(并查集,贪心)
  9. Xsd: Xml序列化、反序列化的利器
  10. Autolayout-VFL语言添加约束-备
  11. freemarker错误七
  12. jQuery的入门操作
  13. Sping--AOP--XML
  14. Leetcode_110_Balanced Binary Tree
  15. MySQL ERROR 1045 (28000)
  16. Docker 更新镜像
  17. 编译原理子cygwin的使用
  18. json字符串和json对象的相互转化
  19. Python 13 简单项目-堡垒机
  20. 《剑指offer》顺时针打印矩阵

热门文章

  1. W - Doom HDU - 5239 线段树 找取模的规律+求一个很大的数的平方对一个数取模的写法 特别的模数==2^63-2^31
  2. 003_python的str切片,str常用操作方法,for循环,集合,深浅copy
  3. 【Hadoop离线基础总结】oozie的安装部署与使用
  4. Day_13【IO流】扩展案例2_统计键盘录入字符在指定项目文件中出现的次数
  5. Android 开发技术周报 Issue#279
  6. Linux内核驱动学习(六)GPIO之概览
  7. 053.集群管理-Helm部署及使用
  8. [hdu3364]xor方程组消元
  9. go 数组 字符串 切片
  10. xilinx VDMA IP核使用