每天一個設計模式之命令模式

godbmw發表於2018-12-13

作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前採用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. 參考

相關文章