深入理解Java设计模式之命令模式
作者:一指流砂~ 发布时间:2023-11-24 11:06:31
一、什么是命令模式
命令模式是一个高内聚的模式,其定义为:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请 求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
在该类图中,我们看到三个角色:
Receiver
接受者角色:该角色就是干活的角色,命令传递到这里是应该被执行的Command
命令角色:需要执行的所有命令都在这里声明Invoker
调用者角色:接收到命令,并执行命令
二、命令模式的使用场景
使用时机:当需要先将一个函数登记上,然后再以后调用此函数时,就需要使用命令模式,其实这就是回调函数。
有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系
例子:拿订餐来说,客人需要向厨师发送请求,但是完全不知道这些厨师的名字和联系方式,也不知道厨师炒菜的方式和步骤。 命令模式把客人订餐的请求封装成 command 对象,也就是订餐中的订单对象。这个对象可以在程序中被四处传递,就像订单可以从服务员手中传到厨师的手中。这样一来,客人不需要知道厨师的名字,从而解开了请求调用者和请求接收者之间的耦合关系
三、命令模式的优缺点
优点:
类间解耦:调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用Command 抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。可扩展性:Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严 重的代码耦合。命令模式结合其他模式会更优秀:命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少 Command子类的膨胀问题。
缺点:
命令模式也是有缺点的,请看Command的子类:如果有N个命令,问题就出来 了,Command的子类就可不是几个,而是N个,这个类膨胀得非常大,这个就需要读者在项 目中慎重考虑使用。
四、命令模式的实现
Receiver
类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接受者
class Receiver
{
public void Action()
{
Console.WriteLine("执行请求!");
}
}
Command
类,用来声明执行操作的接口
abstract class Command
{
protected Receiver receiver;
public Command(Receiver receiver)
{
this.receiver = receiver;
}
abstract public void Execute();
}
ConcreteCommand
类,将一个接受者对象绑定于一个动作,调用接受者相应的操作,以实现Execute。
class ConcreteCommand : Command
{
public ConcreteCommand(Receiver receiver) : base(receiver)
{
}
public override void Execute()
{
receiver.Action();
}
}
Invoker
类,要求该命令执行这个请求
class Invoker
{
private Command command;
public void SetCommand(Command command)
{
this.command = command;
}
public void ExecuteCommand()
{
command.Execute();
}
}
客户端代码
static void Main(string[] args)
{
Receiver r = new Receiver();
Command c = new ConcreteCommand(r);
Invoker i = new Invoker();
i.SetCommand(c);
i.ExecuteCommand();
Console.Read();
}
五、总结
命令模式的意图是将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。
命令模式主要解决的问题是在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。
在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合,这是命令模式的使用场景。
系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式
命令模式的实现过程通过调用者调用接受者执行命令,顺序:调用者→接受者→命令。
来源:https://www.cnblogs.com/xuwendong/p/9814421.html


猜你喜欢
- webservice 可以用于分布式应用程序之间的交互,和不同程序之间的交互。概念性的东西就不说太多,下面开始创建一个简单的webservi
- 前言有些业务比较复杂,比如我们需要新建10张表,每张表有10个字段,如果用手工来操作,肯定非常浪费时间,而且随着代码中对实体类的修改,还要同
- 前言最近和前端联调接口,需要进行一个省市区联动,最终定的方案是通过接口返回一个树形结构给前端,类似这样的结构:下面就把相关表和代码分享给大家
- 前言:在 Java 语言中,保证线程安全性的主要手段是加锁,而 Java 中的锁主要有两种:synchronized 和 Lock,我们今天
- 前言Spring5带来了新的响应式web开发框架WebFlux,同时,也引入了新的HttpClient框架WebClient。WebClie
- java多态性多态分两种:(1) 编译时多态(设计时多态):方法重载。(2) 运行时多态:J
- 标准c++中string类函数介绍注意不是CString之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者
- 引言Java * 机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理
- 对于现在的 App 来说,布局页面基本都会用到沉浸式状态栏,单纯的沉浸式状态栏很容易解决,但是在华为手机上存在一个底部虚拟按键的问题,会导致
- 前言在日常开发中,圆形的图片效果还是很常见的。可以通过给Paint设置Xfermode来实现,这里简单记录如下。实现实现圆形效果的核心是Po
- 基于servlet+jsp+jdbc的后台管理系统,包含5个模块:汽车账户部管理、租车账户部管理、汽车信息管理表、租车记录表、租车租聘表。功
- Purpose开发人员在合作的时候经常遇到以下场景:1.开发人员A在自己的本地数据库做了一些表结构的改动,并根据这些改动调整了DAO层的代码
- 前段时间做课程作业网站后端,运用Spring boot+MyBatis的框架进行设计,Postman进行接口的检测,出现了一些问题。出现的问
- 本文实例讲述了Android ActionBar搜索功能用法。分享给大家供大家参考,具体如下:使用ActionBar SearchView时
- Android指定SnackBar在屏幕的位置Snackbar 常以一个小的弹出框的形式,出现在手机屏幕下方或者桌面左下方,并且是在屏幕所有
- 一 前言这篇文章是很基础的一文,没多大深度,对于开发人员必然是熟练于心。本篇文章的主题是为什么java要设置类成员访问级别?其原因也很简单,
- 今天在做数据分页显示的时候遇到了一个问题,经过测试,证实是Tomcat 6的一个bug,我所用的版本为:apache-tomcat-6.0.
- 本文实例为大家分享了Android实现蒙板效果的相关代码,供大家参考,具体内容如下1、不保留标题栏蒙板的实现效果:原理:1、弹窗时,设置背景
- WebFlux服务编排WebFlux 服务编排是指使用 WebFlux 框架来编排多个异步服务的执行顺序和数据流动,从而构建出一个完整的、基
- 1.二叉树的概念及结构 ①概念:一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二