Javascript実践におけるコマンドモードの詳しい説明

Javascript実践におけるコマンドモードの詳しい説明

意味

リクエストをオブジェクトとしてカプセル化することで、異なるリクエストを持つ他のオブジェクトをパラメーター化したり、リクエストをキューに登録したりログに記録したり、元に戻せる操作をサポートしたりできるようになります。

「コマンド パターン」は「リクエスト」をオブジェクトにカプセル化することで、元に戻す操作をサポートしながら、他のオブジェクトを異なるリクエスト、キュー、またはログを使用してパラメータ化できるようにします。

ここでの「リクエスト」の定義は、フロントエンドでよく言われる「Ajax リクエスト」ではなく、アクションを開始することを意味する「アクション リクエスト」です。たとえば、リモコンを使ってテレビの電源を切るときは、「電源を切って」がリクエストになります。コマンド パターンでは、リクエストをコマンドに抽象化します。このコマンドは再利用可能で、受信者 (テレビ) のみを考慮します。アクションの開始側 (リモコン) は、サポートするコマンドのみを考慮しますが、これらのコマンドが具体的に何を行うかは考慮しません。

構造

コマンド パターンのクラス図は次のとおりです。

このクラス図には、5 つの役割があります。

  • クライアント - 具体的なコマンドとレシーバー (アプリケーション層) を作成します。
  • 呼び出し側 - コマンドの発行者。通常はコマンド オブジェクトを保持し、複数のコマンド オブジェクトを保持できます。
  • レシーバー - コマンド レシーバー。実際にコマンドを実行するオブジェクト。コマンドに必要な対応する機能を実装できる限り、どのクラスでもレシーバーになることができます。
  • コマンド - コマンド インターフェース。
  • ConcreteCommand - コマンド インターフェイスの実装。

レシーバーとインボーカーは結合されておらず、機能拡張が必要な​​場合は新しいコマンドが追加されます。そのため、コマンドモードはオープンクローズ原則に準拠しています。

カスタムショートカットキー

ショートカット キーのカスタマイズは、エディターの最も基本的な機能です。コマンド パターンを使用すると、キーの位置とキー ロジックを切り離す構造を記述できます。

インターフェースコマンド{
    実行():void
}

タイプ Keymap = { [キー:文字列]: コマンド }
クラスホットキー{
    キーマップ: キーマップ = {}

    コンストラクタ(キーマップ: キーマップ) {
        this.keymap = キーマップ
    }

    呼び出し(e: キーボードイベント) {
        定数プレフィックス = e.ctrlKey ? 'ctrl+' : ''
        定数キー = プレフィックス + e.key
        this.dispatch(キー)
    }

    ディスパッチ(キー: 文字列) {
        this.keymap[キー].exec()
    }
}

クラスCopyCommandはCommandを実装します{
    コンストラクタ(クリップボード: 任意) {}
    実行() {}
}

CutCommandクラスはCommandを実装します{
    コンストラクタ(クリップボード: 任意) {}
    実行() {}
}

PasteCommandクラスはCommandを実装します{
    コンストラクタ(クリップボード: 任意) {}
    実行() {}
}

const クリップボード = { データ: '' }
定数キーマップ = {
    'ctrl+x': 新しいCutCommand(クリップボード)、
    'ctrl+c': 新しいCopyCommand(クリップボード)、
    'ctrl+v': 新しい PasteCommand(クリップボード)
}
const hotkey = 新しい Hotkey(キーマップ)

document.onkeydown = (e) => {
    ホットキー.call(e)
}

この場合、ホットキーが呼び出し側で、クリップボードが受信者になります。既存のキーマップを変更する必要がある場合は、既存のキーまたはコマンドを追加または置き換えるだけです。

この書き方はお馴染みだと思いますか?はい、Redux もコマンド モードを適用します。Store は Receiver に相当し、Action は Command に相当し、Dispatch は Invoker に相当します。

元に戻すとやり直し

コマンド パターンに基づいて、元に戻すとやり直しをサポートするように簡単に拡張できます。

インターフェース IPerson {
    moveTo(x: 数値, y: 数値): void
}

クラスPersonはPersonを実装します{
    x = 0
    y = 0

    移動先(x: 数値, y: 数値) {
        this.x = x
        this.y = y
    }
}

インターフェースコマンド{
    実行(): 無効
    元に戻す(): 無効
}

MoveCommandクラスはCommandを実装します{
    前X = 0
    前 = 0

    人: 人

    コンストラクタ(人: Person) {
        this.person = 人
    }

    実行() {
        this.prevX = this.person.x
        this.prevY = this.person.y
        this.person.moveTo(this.prevX++、this.prevY++) は、
    }

    元に戻す(){
        this.person.moveTo(this.prevX, this.prevY)
    }
}


const ezio = 新しい Person()
const moveCommand = 新しい MoveCommand(ezio)
移動コマンド.exec()
コンソールログ(ezio.x、ezio.y)
移動コマンド.undo()
コンソールログ(ezio.x、ezio.y)

録音と再生

ゲーム内の録画と再生機能について考えてみましょう。キャラクターの各アクションをコマンドと見なすと、録画中に一連のコマンド キューを取得できます。

クラスコントロール{
    コマンド: コマンド[] = []
    
    exec(コマンド) {
        this.commands.push(コマンド)
        コマンド.exec(this.person)
    }
}

const ezio = 新しい Person()
const コントロール = 新しいコントロール()
control.exec(新しいMoveCommand(ezio))
control.exec(新しいMoveCommand(ezio))

console.log(コントロールコマンド)

コマンド キューがあれば、複数の元に戻す操作とやり直し操作を簡単に実行し、コマンド履歴を実現できます。現在のコマンド キューのポインターを移動するだけです。

クラスコマンド履歴 {
    コマンド: コマンド[] = []
    
    インデックス = 0
    
    現在のコマンドを取得します(){
        this.commands[index]を返す
    }
    
    コンストラクター(コマンド: Command[]) {
        this.commands = コマンド
    }
    
    やり直し(){
        this.index++
        this.currentCommand.exec()
    }
    
    元に戻す() {
        this.currentCommand.undo()
        this.index--
    }
}

同時に、コマンドをオブジェクトにシリアル化すると、保存や送信に使用できるようになります。このようにして、リモート コンピューターに送信し、ezio の動きをリモート制御する機能を実現できます。

[{
    タイプ: '移動'、
    x: 1,
    y: 1,
}, {
    タイプ: '移動'、
    x: 2,
    y: 2,
}]

マクロ

コマンドに対して簡単な処理を行うことで、既存のコマンドを組み合わせて実行し、マクロコマンドとして使用することができます。

クラスBatchedCommandはCommandを実装します{
    コマンド = []
    
    コンストラクタ(コマンド) {
        this.commands = コマンド
    }
    
    実行() {
        this.commands.forEach(コマンド => command.exec())
    }
}

const batchedMoveCommand = 新しいBatchedCommand([
    新しいMoveCommand(ezio)、
    新しいSitCommand(ezio)、
])

バッチ化されたMoveCommand.exec()

要約する

上記の例から、コマンド モードには次の特性があることがわかります。

  • 低結合により、受信者と発信者間の結合が完全に排除されます。
  • 拡張が容易で、新しいコマンドを追加するだけで新しい機能を拡張できます。
  • シリアル化をサポートし、保存と転送が容易になります。
  • これにより、コマンド クラスが簡単に大きくなる可能性があります。

以上がJavascript実践におけるコマンドモードの詳細な説明です。Javascriptコマンドモードの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • メンテナンス可能なオブジェクト指向 JavaScript コードの作成
  • JavaScript を使用してメンテナンス可能なスライドショー コードを作成する
  • JavaScriptのURLオブジェクトとは何かについて話しましょう
  • JavaScript における正規表現の実際的な応用の詳細な説明
  • JavaScript で配列遅延評価ライブラリを実装する方法
  • 独自のネイティブ JavaScript ルーターを作成する方法
  • JavaScript でアルゴリズムの複雑さを学ぶ方法
  • いくつかの面接の質問を使ってJavaScriptの実行メカニズムを調べる
  • メンテナンス可能なJSコードの書き方を教えます

<<:  一般的な MySQL ストレージ エンジンとパラメータ設定およびチューニングの紹介

>>:  Dockerデータボリューム操作の実装

推薦する

ウェブデザイナーは適した人材

<br />この世に道はない。より多くの人が歩くようになると、それは道になります。最初は...

Windows 10 での MySQL 8.0.11 圧縮バージョンのインストール チュートリアル

この記事では、MySQL 8.0.11圧縮版のインストールチュートリアルを参考までに紹介します。具体...

デザイン理論: なぜ私たちは間違った場所を見ているのでしょうか?

数日前、バスで仕事に行きました。バスのカードリーダーの実際の使用シーンを実際に見て、カードリーダーの...

Windows で MySQL データベースを別のディスクに移動する

序文今日、MySQL をインストールしたところ、データベース ストレージがデフォルトで C ドライブ...

フォーム要素の簡単な実装コードでは登録を例に挙げています

コード実装:コードをコピーコードは次のとおりです。 <!DOCTYPE html> &l...

VMware 仮想マシンでの Centos8 ブリッジの静的 IP 設定方法

1. ネットワーク接続方法がブリッジされていることを確認する物理ネットワーク接続ステータスのコピーを...

光沢のある輝くウェブサイトデザインの感動的なデザイン例

このコレクションには、あなたのデザインアイデアにインスピレーションを与える、輝いて光沢のある、優れた...

Zabbix設定 DingTalkアラーム機能実装コード

必要Zabbix で DingTalk アラームを設定する方法は、Prometheus で Ding...

デカルト積原理を使用してMySQLで複数のテーブルをクエリする方法を簡単に説明します。

MySQL マルチテーブルクエリ (直積原理)まず、データが使用するテーブルを決定します。デカルト...

CocosCreator ユニバーサルフレームワークデザインネットワーク

目次序文Websocketの使用Websocketオブジェクトの構築Websocket ステータスW...

JDBC が MySQL に接続して中国語を処理するときに文字化けする問題の解決方法の詳細説明

JDBC が MySQL に接続して中国語を処理するときに文字化けする問題の解決方法の詳細説明最近、...

MySQLがファントムリードを解決する方法の詳細な説明

1. ファントムリーディングとは何ですか?トランザクションにおいて、複数のクエリの後に結果セットの数...

HTML の META タグの使用に関するヒントの例

HTML メタタグHTML メタタグは、Web ページのコンテンツに関する情報をブラウザや検索エンジ...

ポータルサイトのフォーカス画像のデザインに関するいくつかの結論

フォーカス画像は、画像、テキスト、動的なインタラクティブ効果を統合したコンテンツを表示する方法です。...

React ページ ターナーの実装 (フロント エンドとバックエンドを含む)

目次フロントエンド上記のアイデアに従って、ページめくり機能を設計して記述します。バックエンド(Jav...