详解command设计模式,解耦操作和回滚
大家好,欢迎来到设计模式专题,我们的主旨是介绍一些有趣好玩的设计模式。
今天我们介绍的设计模式叫做命令模式(command),在这个模式下,我们可以实现do和undo的解耦,让使用方不用关心内部的实现细节。
command模式
这个模式我们在日常当中经常使用,举一个很简单的例子,比如说我们发布代码。发布了之后发现不小心发布上去了一个bug,这个时候我们应该做什么?很简单,就是回滚,把线上的代码回滚到这一次发布之前的代码。这样我们这次发布带来的改动就会被消除,那么就避免了bug的产生。
那么,对于一个发布系统来说,它需要做什么?其实也就是两个功能,一个是发布另外一个是回滚。这两个操作是互相可逆的,对于它的使用者来说,是不会关心它的内部是如何实现的,我们只需要在页面上按按钮就好了。
我们来回顾一下这个过程,我们点击发布,可以把最新的代码发布上线。发布之后发现问题,再点击回滚,系统再自动恢复到发布之前的状态。发布和回滚彼此是可逆的,当我们消除掉bug之后,再次点击发布,又可以再次发布最新的代码了。
command模式就是做的这个事情,也就是对do和undo的封装。我们来看一个很简单的例子,对文件改名。比如说我们要把系统当中的文件改名,从A.txt改成B.txt。这个功能很简单,系统为我们提供了现成的函数,叫做os.rename(),我们只需要把A和B两个文件的地址传入其中即可。
假如我们发现改名字改错了,想回滚怎么办呢?会发现我们改动之前的名字已经忘了,不知道怎么回滚了。这个时候就可以使用command模式,我们来看代码:
import os
class MoveFileCommand:
def __init__(self, src, dest):
self.src = src
self.dest = dest
def execute(self):
self.rename(self.src, self.dest)
def undo(self):
self.rename(self.dest, self.src)
def rename(self, src, dest):
print('renaming from {} to {}'.format(src, dest))
os.rename(src, dest)
在execute方法当中,我们把文件从src变成了dest,如果想要回滚,它又会再次调用rename。将文件名从dest回滚到src。这样的话,作为使用方就可以完全不用理解api内部的实现逻辑了,不然的话为了防止改错了的情况,还需要做很多适配。
menu item
有了command模式之后我们可以在外面在封装一层用来ui交互上,我们很常见的一种UI交互方式就是按钮。某一个按钮点一下之后会出现一个按过的标记,并且实现一个什么功能。再按一次标记消失,功能也随之关闭。
我随便找了一个例子,比如下图菜单当中的show minimap,show breadcrumbs这些都是这样的功能。点一下出现缩略图,再点一下缩略图消失。

如果你写过UI页面的话,一般来说我们会先定义一个Menu Item的类,表示菜单当中的所有的item的基类。不同的选项表示不同的item,我们进一步分析会发现有些item我们需要这样双击关闭的机制,而有些item是没有的。比如上面的Run、Output这些item都是点一次执行一次的。
我们当然可以把上面介绍的Command对象直接当做item,但是这样不利于整个菜单的统一,所以我们还会在外面包一层。比如所有MenuItem的父类应该是这样的:
class MenuItemBaseClass:
def __init__(self):
pass
def pressed(self):
pass
def unpress(self):
pass
有了这个基类之后,我们就可以实现一个可回滚的类,将command的对象作为类成员变量,再在其中实现unpress方法:
class RedoableMenu(MenuItemBaseClass):
def __init__(self, command):
self_command = command
def pressed(self):
self._command.execute()
def unpress(self):
self._command.undo()
这样我们的UI就和command解耦了,如果我们想要实现不同的可以回滚的功能, 只需要实现不同的command创建实例就可以了。对于整个UI的使用没有任何影响,UI组件当中用到的所有类都是统一的。可能在Python这种弱类型语言当中看不太出来,因为我们一个list说是menu基类的list,但是其实装什么都行。但如果是强类型语言,那么这种抽象和封装就是非常有必要的了。
今天的文章就到这里,衷心祝愿大家每天都有所收获。如果还喜欢今天的内容的话,请来一个三连支持吧~(点赞、关注、转发)
- END -
{{uploading-image-118988.png(uploading...)}}
详解command设计模式,解耦操作和回滚的更多相关文章
- MySQL【Update误操作】回滚(转)
前言: 继上一篇MySQL[Delete误操作]回滚之后,现在介绍下Update回滚,操作数据库时候难免会因为“大意”而误操作,需要快速恢复的话通过备份来恢复是不太可能的,因为需要还原和bi ...
- java SSM多操作注解回滚
在业务操作时难免会遇到一个业务多操作,会用到事物回滚这里写了一个简单的多操作失败事物回滚案例 在这之前你需要在你的applicationContext-mybatis.xml中配置: <!-- ...
- java开发中的23中设计模式详解--大话设计模式
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- RDD的详解、创建及其操作
RDD的详解 RDD:弹性分布式数据集,是Spark中最基本的数据抽象,用来表示分布式集合,支持分布式操作! RDD的创建 RDD中的数据可以来源于2个地方:本地集合或外部数据源 RDD操作 分类 转 ...
- 算法进阶面试题01——KMP算法详解、输出含两次原子串的最短串、判断T1是否包含T2子树、Manacher算法详解、使字符串成为最短回文串
1.KMP算法详解与应用 子序列:可以连续可以不连续. 子数组/串:要连续 暴力方法:逐个位置比对. KMP:让前面的,指导后面. 概念建设: d的最长前缀与最长后缀的匹配长度为3.(前缀不能到最后一 ...
- EditPlus正则表达式中英文详解(附常用事例操作)
http://www.cnblogs.com/JustinYoung/articles/editplus_regular_expression.html EditPlus正则表达式中英文详解 \t T ...
- pandas常用操作详解——pandas的去重操作df.duplicated()与df.drop_duplicates()
df.duplicated() 参数详解: subset:检测重复的数据范围.默认为数据集的所有列,可指定特定数据列: keep: 标记哪个重复数据,默认为'first'.1.'first':标记重复 ...
- 详解java设计模式之责任链模式
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt175 从击鼓传花谈起 击鼓传花是一种热闹而又紧张的饮酒游戏.在酒宴上宾客依次 ...
- 详解JS设计模式
原文链接:www.cnblogs.com 一:理解工厂模式 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式. 简单的工厂模式可以理解为解决 ...
随机推荐
- JavaScript浮点数及其运算
.普及两个函数Math.pow(底数,几次方)Number.toFixed(小数位数)2.浮点数相加function accAdd(arg1,arg2){ var r1,r2,m; try{r ...
- Linux:nginx基础
一..简单介绍 nginx时开源的www服务器,只能解析静态的网页(html,js,css等),具有静态小文件高并发特性. 可做web服务器.负载均衡.web cache(web缓存) 优点: 1.高 ...
- 白嫖党看番神器 AnimeSeacher
- Anime Searcher - 简介 通过整合第三方网站的视频和弹幕资源, 给白嫖党提供最舒适的看番体验~ 目前有 4 个资源搜索引擎和 2 个弹幕搜索引擎, 资源丰富, 更新超快, 不用下载, ...
- elasticsearch跨集群数据迁移
写这篇文章,主要是目前公司要把ES从2.4.1升级到最新版本7.8,不过现在是7.9了,官方的文档:https://www.elastic.co/guide/en/elasticsearch/refe ...
- oracle之字符集
全球化特性与字符集 数据库的全球化特性是数据库发展的必然结果,位于不同地区.不同国家.不用语言而使用同一数据库越来越普遍.Oracle数据库提供了对全球化数据库的支持,消除不同文字.语言环境.历法货币 ...
- Robotframework自动化2-Windows环境搭建
前言 上节主要介绍了部分的robotframework搭建,如果想运行APP的话,还需要进一步配置环境. 需要安装的软件 1.Android-sdk-windows 2.JDK 3.Appium-de ...
- 2.Strom-入门案例
- VUE3.0发布,自己搞个文档网站
9月19日,尤大神发表了VUE3.0版本的演说,强大且震撼,这两天一直在找网站文档,可能还未被百度收录,未找到文档网站.后来在github上面找到了中文代码. 地址为:https://github.c ...
- BTRsys1~2系列靶机渗透
BTRsys系列靶机渗透 BTRsys1 端口发现加目录扫描. 发现目录:http://192.168.114.161/login.php 尝试弱密码失败,查看源代码. <script type ...
- [0CTF 2016]piapiapia(反序列逃逸)
我尝试了几种payload,发现有两种情况. 第一种:Invalid user name 第二种:Invalid user name or password 第一步想到的是盲注或者报错,因为fuzz一 ...