三分钟理解“命令模式”——设计模式轻松掌握

什么是命令模式?

假设现在有一个请求处理类(低层类/第三方类),如果客户端拿到这个类之后直接调用它,那么客户端和这个请求处理类之间的藕合度过高。

这时候我们在客户端的请求发送类和请求处理类之间增加一个Invoker类,再将请求发送类发送的所有请求封装成对象,然后让Invoker类去管理这些请求对象,并决定这些请求是否允许执行、何时执行、按什么顺序执行。

由于在请求发送类和请求处理类之间增加了请求转发者,因此这两个类之间的藕合度就大大降低。

命令模式的类图

1.Invoker类用于管理客户端想要发送的请求Command;

Invoker中有一个List<Command>,用于存放客户端发来的还没有被执行的请求;

客户端通过Invoker类中的add、delete函数,向Invoker发送或删除请求;

客户端通过Invoker类的executeCommand()函数,一次性执行Invoker中尚未被执行的请求。

2.当客户端执行Invoker的executeCommand()函数时,该函数实际调用了当前Command对象肚子中的executeCommand()函数。

Command类中含有请求处理者Receiver的对象,客户端通过Command对象中的setReceiver(Receiver)函数来设置;

当客户端调用Invoker的executeCommand()时,该函数调用了当前Command对象的executeCommand()函数,该函数再调用Command肚子中那个Receiver对象的具体处理函数。

客户端代码:

main(){
	//创建Receiver对象
	Receiver receiver = new Receiver();

	//创建Command对象,并往Command肚子里设置该命令所要执行的处理类的对象
	Command commandA = new ConcreteCommandA();
	commandA.setReceiver(receiver);

	Command commandB = new ConcreteCommandB();
	commandB.setReceiver(receiver);

	//创建Invoker对象,并往它肚子里添加需要处理的命令
	Invoker invoker = new Invoker();
	invoker.add(commandA);
	invoker.add(commandB);

	//执行Invoker肚子里的所有命令
	invoker.executeCommand();
}

命令模式的优点

1.命令模式将请求发送者和请求处理者分离开,从而降低了这两个类之间的藕合;

2.通过在请求发送者和请求处理者之间增加转发类的方式,从而客户端发出的请求可以在被处理之前都存放在Invoker类的容器中,请求在被执行前就有了一个缓冲,能起到以下作用:

a)Invoker能够对客户端发出的请求进行排序;

b)Invoker能够决定是否需要驳回请求;

c)客户端可以在请求被执行前选择撤销某个请求;

d)在需要的情况下,客户端的请求可以被记录成日志;

3.增加新的命令时只需增加新的命令子类即可。

是否需要在程序设计的时候去猜测未来可能发生的事情?

不需要!敏捷开发原则告诉我们:不要为代码添加基于猜测的功能!

如果不清楚一个系统是否需要命令模式,就不要着急着去实现它;在需要的时候通过重构代码实现这个模式。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏容器云生态

Openstack平台搭建之第二天

Openstack平台搭建之第二天 If you have any question ,please contact me by weichuangxxb@si...

28010
来自专栏草根专栏

使用Identity Server 4建立Authorization Server (4)

上一篇讲了使用OpenId Connect进行Authentication. 下面讲 Hybrid Flow和Offline Access 目前我们解决方案里面...

4485
来自专栏Create Sun

mvc file控件无刷新异步上传操作

前言   上传文件应该是很常见必不可少的一个操作,网上也有很多提供的上传控件。今天遇到一个问题:input控件file无法进行异步无刷新上传。真真的感到别扭。所...

3267
来自专栏魏琼东

基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - 插件接口IModule扩展

      前面的文章AgileEAS.NET之插件接口IModule和AgileEAS.NET之插件运行容器中对插件的基本契约宝义和运行容器做了一个介绍,但是...

1878
来自专栏农夫安全

BurpSuite中的安全测试插件推荐

? 首先放出一张小编一直在用的几个插件~ 0x00 前言 ? 0x01 AuthMatrix AuthMatrix是一款用于检测越权漏洞的Burp ...

4175
来自专栏林德熙的博客

从以前的项目格式迁移到 VS2017 新项目格式 必须删除必须修改添加文件项目引用引用包删除多余文件输入注释多个框架使用条件判断迁移 WPF 项目

以前的项目格式使用的是 csproj 的格式,但是 .net core 支持使用 project.json 格式的项目文件,后来还是决定不使用这个格式。 VS2...

552
来自专栏NetCore

Do you kown Asp.Net Core -- 配置Kestrel端口

Kestrel介绍 在Asp.Net Core中,我们的web application 其实是运行在Kestrel服务上,它是一个基于libuv开源的跨平台可运...

2308
来自专栏MelonTeam专栏

Password Auto Fill

前言 在 WWDC 17 Session 206 中,介绍了这个 iOS 11 加入的新功能。尽管这个功能特别简单,但几乎是今年所有发布的新功能中我最喜欢的一...

1946
来自专栏向治洪

Android监听自身卸载,弹出用户反馈调查

1,情景分析         在上上篇博客中我写了一下NDK开发实践项目,使用开源的LAME库转码MP3,作为前面几篇基础博客的加深理解使用的,但是这样的项目用...

2125
来自专栏菩提树下的杨过

c#中开发ActiveX的学习笔记

1.为什么要用ActiveX? 网页本身的功能是有限的,要想实现一些网页本身不支持的功能,比如:网页上的p2p视频播放,就得靠ActiveX这种古老的技术。 2...

1905

扫描关注云+社区