当前位置: 首页 > news >正文

每天一个设计模式之命令模式

作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用 javascriptpython两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :)

原文地址是:《每天一个设计模式之命令模式》

欢迎关注个人技术博客:godbmw.com。每周 1 篇原创技术分享!开源教程(webpack、设计模式)、面试刷题(偏前端)、知识整理(每周零碎),欢迎长期关注!

如果您也想进行知识整理 + 搭建功能完善/设计简约/快速启动的个人博客,请直接戳theme-bmw

0. 示例代码

  • 此节全部代码
  • 《每天一个设计模式》地址

1. 什么是“命令模式”?

命令模式是一种数据驱动的设计模式,它属于行为型模式。
  1. 请求以命令的形式包裹在对象中,并传给调用对象。
  2. 调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象。
  3. 该对象执行命令。

在这三步骤中,分别有 3 个不同的主体:发送者、传递者和执行者。在实现过程中,需要特别关注。

2. 应用场景

有时候需要向某些对象发送请求,但是又不知道请求的接受者是谁,更不知道被请求的操作是什么。此时,命令模式就是以一种松耦合的方式来设计程序

3. 代码实现

3.1 python3 实现

命令对象将动作的接收者设置在属性中,并且对外暴露了execute接口(按照习惯约定)。

在其他类设置命令并且执行命令的时候,只需要按照约定调用Command对象的execute()即可。到底是谁接受命令,并且怎么执行命令,都交给Command对象来处理!

__author__ = 'godbmw.com'

# 接受到命令,执行具体操作
class Receiver(object):
  def action(self):
    print("按钮按下,执行操作")

# 命令对象
class Command:
  def __init__(self, receiver):
    self.receiver = receiver

  def execute(self):
    self.receiver.action()

# 具体业务类
class Button:
  def __init__(self):
    self.command = None

  # 设置命令对戏那个
  def set_command(self, command):
    self.command = command

  # 按下按钮,交给命令对象调用相关函数
  def down(self):
    if not self.command:
      return
    self.command.execute()

if __name__ == "__main__":

  receiver = Receiver()

  command = Command(receiver)

  button = Button()
  button.set_command(command)
  button.down()

3.2 ES6 实现

setCommand方法为按钮指定了命令对象,命令对象为调用者(按钮)找到了接收者(MenuBar),并且执行了相关操作。而按钮本身并不需要关心接收者和接受操作

// 接受到命令,执行相关操作
const MenuBar = {
  refresh() {
    console.log("刷新菜单页面");
  }
};

// 命令对象,execute方法就是执行相关命令
const RefreshMenuBarCommand = receiver => {
  return {
    execute() {
      receiver.refresh();
    }
  };
};

// 为按钮对象指定对应的 对象
const setCommand = (button, command) => {
  button.onclick = () => {
    command.execute();
  };
};

let refreshMenuBarCommand = RefreshMenuBarCommand(MenuBar);
let button = document.querySelector("button");
setCommand(button, refreshMenuBarCommand);

下面是同级目录的 html 代码,在谷歌浏览器中打开创建的index.html,并且打开控制台,即可看到效果。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>命令模式</title>
  </head>
  <body>
    <button>按钮</button>
    <script src="./main.js"></script>
  </body>
</html>

4. 参考

  • 《JavaScript 设计模式和开发实践》
  • 如何实现命令模式

相关文章:

  • ESXi虚拟机的磁盘格式
  • Nmap的详细使用
  • js 如何判断数组元素是否存在重复项
  • Kubernetes高可用负载均衡与集群外服务访问实践
  • K8S-网络模型、POD/RC/SVC YAML 语法官方文档
  • C# 图解教程 第四章 类的基本概念
  • [译] Android 内核控制流完整性
  • codeforces 1093 题解
  • IIS 设备未就绪。
  • 性能常用指标(重点)
  • python的内存回收机制即gc模块讲解
  • 前端工程师的 2018 年总结 | 掘金年度征文
  • 剑指 linux、docker、k8s
  • 快手服务治理平台KESS的设计理念和实战
  • 服务器巡检常用命令,脚本,及调优思路
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【知识碎片】第三方登录弹窗效果
  • 2018一半小结一波
  • JSONP原理
  • LeetCode算法系列_0891_子序列宽度之和
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • Sublime text 3 3103 注册码
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • 多线程 start 和 run 方法到底有什么区别?
  • 计算机常识 - 收藏集 - 掘金
  • 前端工程化(Gulp、Webpack)-webpack
  • 一个完整Java Web项目背后的密码
  • 《码出高效》学习笔记与书中错误记录
  • ​【已解决】npm install​卡主不动的情况
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • #{}和${}的区别是什么 -- java面试
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • $L^p$ 调和函数恒为零
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (未解决)macOS matplotlib 中文是方框
  • (原)本想说脏话,奈何已放下
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .bat文件调用java类的main方法
  • .NET Core WebAPI中封装Swagger配置
  • .NET Core中Emit的使用
  • .NET MVC第五章、模型绑定获取表单数据
  • .net/c# memcached 获取所有缓存键(keys)
  • .net程序集学习心得
  • .Net高阶异常处理第二篇~~ dump进阶之MiniDumpWriter
  • .Net转Java自学之路—SpringMVC框架篇六(异常处理)
  • @Autowired自动装配
  • [ 网络基础篇 ] MAP 迈普交换机常用命令详解
  • [2023年]-hadoop面试真题(一)
  • [C#7] 1.Tuples(元组)