デザインパターン - コマンドモード(コマンド)

より多くの成長のための第JavaStorm世間の注目。

これは、読むために約6分かかります。提案を読んだ後のコレクション。
コマンドモード動作またはパッケージオブジェクトへの要求。コマンドモードでは、システムは、クライアント・パラメータの異なる要求を使用することができ、要求キューまたはログ要求、およびアンドゥコマンドの回復を提供することができます。
GitHubの住所:https://github.com/UniqueDong/zero-design-stuコード頭から下のパッケージ。

アウトライン

コマンドのコマンドモードが封入されています。コマンドコマンドの責任を発行するモードとコマンドを実行する責任は、異なるオブジェクトに割り当てられ、分離しました。

各コマンドは、操作ある:要求する要求当事者は、必要な操作を実行し、受信側は、要求を受信し、動作を行います。モードは、その要求当事者が要求を受信する1のインターフェースを知る必要がないということではなく、それが実行されたとき、操作が行われているかどうか、要求が受信された方法を知っている、とし、一つのコマンドでオープンな独立した受信要求のいずれかを可能にし、どのようにそれが実行されます。

コマンドは、一方の当事者の要求を可能にするので、次のような利点を有するように、要求が独立して進化することができます受信します。

(1)コマンドモードので、新しいコマンドが容易にシステムに追加すること。

(2)一方が受信した要求が拒否される要求であるかどうかを決定することを可能にします。

(3)は、より簡単にコマンドキューを設計することができます。

(4)が容易にアンドゥおよびリドゥ要求に実現することができます。

(5)必要な場合には、より簡単にコマンドがログに記録することができます。
クラス図

役割

  • クライアント(クライアント)役割: ConcreteCommandを作成し、その受信者を設定します。
  • コマンド(コマンド)役割:すべてのコマンドへのインタフェースを宣言する。コマンドオブジェクトは、メソッドはインターフェースも同僚アンドゥ()メソッドは、脱退した、受信者は、関連するアクションを実行できるようにすることができ、実行を呼び出します。
  • 特定の順序(ConcreteCommand)役割:レシーバと定義挙動との間の弱い結合は、execute()メソッドを実装し、対応する呼受信者の操作に責任があります。execute()メソッドは、通常、実行方法と呼ばれています。唯一の方法は要求することができ、その後、1つ以上のアクションは、受信者ConcreteCommandによって呼び出される実行発信者が必要。
  • 呼び出し側(実行者)の役割:メソッドを実行するコマンドオブジェクトを保持するために、呼び出し側がメソッド呼び出しトリガーコマンドオブジェクトを提供し、コマンドが実行されます。
  • レシーバ(受信機)の役割:リクエストを実行し、実行を担当。任意のクラスは、受信、要求の実行方法とアクションメソッドと呼ぶことができます。

実装プロセス

  1. クライアントは、コマンドオブジェクトを作成します。
  2. SetCommandクライアントは、呼び出し元のオブジェクトのメソッドを呼び出します。
  3. 時間内の次の適切な時点において、発呼者は、コマンドオブジェクトの実行メソッドを呼び出します。
  4. このコマンドは、発信者によって行われ、対応する受信者に委託しました。タスクを完了します。

シーンのシミュレーション

Aプログラマブルリモコン多目的6つのスロット(それぞれが異なる家電機器を指定してもよい)、家電製品(テレビ、エアコン、冷蔵庫、ステレオ)を制御します。各スロットは、対応する[ON]を[OFF]ボタンを有しています。また、ボタンを撤回し、全体のAキーを持っています。ランプが消灯しているなどの需要が例撤退で、その後、ライトをオンにするボタン開かれたを押してください。[元に戻す]ボタンが押された場合さて、その後、アクションが逆になります。ここでは、ライトがオフになります。
リモートコントロール
対応するスロットに接続されたアプライアンスは、対応する命令がスイッチです。2つの命令、すなわち、[開く]および[OFF]ボタンに対応する各器具。

多くの家電製品はsetVolumn()、setTV()、の数に加えて、(上)と()メソッドオフ持って設定温度() メソッド。
我々は()light.onその後、スロット1 ==ライトあれば書き込むことはできません 。

コードの実装

コマンド受信者の役割

まず、我々は、家電製品の多くを持っています。実際に、彼らは異なるコマンドの実行のための聴衆です。

  • ライト
package com.zero.headfirst.command.receiver;

public class Light {
    public void on() {
        System.out.println("打开电灯。");
    }
    public void off() {
        System.out.println("关灯。");
    }
}

package com.zero.headfirst.command.receiver;

public class Stereo {
    public void on() {
        System.out.println("打开音响");
    }

    public void off() {
        System.out.println("关闭音响");
    }

    public void setCD() {
        System.out.println("放入CD");
    }

    public void setVolume() {
        System.out.println("音响音量设置为20");
    }
}

コマンドの役割

それぞれ、このインタフェースを実装するすべてのコマンドオブジェクト、コマンド実行や撤退の最初の

package com.zero.headfirst.command;

/**
 * 命令(Command)角色
 */
public interface Command {
    /**
     * 命令执行
     */
    void execute();

    /**
     * 命令撤销
     */
    void undo();
}

特定のコマンドの役割

  • 定義されたコマンドは実行達成するために点灯します。コマンド受信部は、発信者がランプが点灯を行う対応する動作を実行するデリゲートを呼び出したときにように、参照光を保持しています。
package com.zero.headfirst.command.impl;

import com.zero.headfirst.command.Command;
import com.zero.headfirst.command.receiver.Light;

public class LightOnCommand implements Command {

    /**
     * 持有接受者实例,以便当命令execute执行的时候由接受者执行开灯
     */
    private Light light;

    @Override
    public void execute() {
        light.on();
    }

    @Override
    public void undo() {
        light.off();
    }

    /**
     * 设置命令的接受者
     * @param light
     */
    public void setLight(Light light) {
        this.light = light;
    }
}

  • 定義されたコマンドライト
package com.zero.headfirst.command.impl;

import com.zero.headfirst.command.Command;
import com.zero.headfirst.command.receiver.Light;

public class LightOffCommand implements Command {

    /**
     * 持有接受者实例,以便当命令execute执行的时候由接受者执行
     */
    private Light light;

    @Override
    public void execute() {
        light.off();
    }

    @Override
    public void undo() {
        light.on();
    }

    public void setLight(Light light) {
        this.light = light;
    }
}

  • オープンサウンド定義されたコマンド
package com.zero.headfirst.command.impl;

import com.zero.headfirst.command.Command;
import com.zero.headfirst.command.receiver.Stereo;

/**
 * 音响开指令
 */
public class StereoOnCommand implements Command {

    private Stereo stereo;

    @Override
    public void execute() {
        stereo.on();
        stereo.setCD();
        stereo.setVolume();
    }

    @Override
    public void undo() {
        stereo.off();
    }

    public void setStereo(Stereo stereo) {
        this.stereo = stereo;
    }
}

  • 閉じるコマンド定義された音
package com.zero.headfirst.command.impl;

import com.zero.headfirst.command.Command;
import com.zero.headfirst.command.receiver.Stereo;

public class StereoOffCommand implements Command {

    private Stereo stereo;

    public void setStereo(Stereo stereo) {
        this.stereo = stereo;
    }

    @Override
    public void execute() {
        stereo.off();
    }

    @Override
    public void undo() {
        stereo.on();
        stereo.setCD();
        stereo.setVolume();
    }
}

テレビの上の残りの電源を入れ、テレビの電源を切り、エアコンをオンにし、接近していない1の空気の書き込みに。テンプレートは、同じルーチンです。今、具体的なコードはGitHubのアドレスは、次のことができます。https://github.com/UniqueDong/zero-design-stuをコード頭から下のパッケージ。

呼び出し側の役割

実際には、私たちのリモコン。

package com.zero.headfirst.command;

import com.zero.headfirst.command.impl.NoCommand;

import java.util.Arrays;

/**
 * 调用者:遥控器
 */
public class RemoteControl {
    /**
     * 一共4个家电插槽,每个插槽有 开与关命令。
     */
    private Command[] onCommands;
    private Command[] offCommands;

    //用来保存前一个命令,用来实现撤销功能
    private Command undoCommand;

    /**
     * 通过构造器初始化开关数组
     */
    public RemoteControl() {
        onCommands = new Command[4];
        offCommands = new Command[4];
        //初始化所有插槽为空指令
        Command noCommand = new NoCommand();
        for (int i = 0; i < 4; i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
        //一开始没有所谓的前一个命令,所以默认无指令
        undoCommand = noCommand;
    }

    /**
     * 设置指定插槽对应的按钮指令
     * @param slot 插槽位置
     * @param onCommand 开指令
     * @param offCaommand 关指令
     */
    public void setCommand(int slot,Command onCommand, Command offCaommand) {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCaommand;
    }

    /**
     * 模拟按下指定插槽对应的【开】按键
     */
    public void pressOnButton(int slot) {
        onCommands[slot].execute();
        //将当前指令记录下来,用于在撤销的时候能执行命令对应的 undo 方法从而实现撤销功能
        undoCommand = onCommands[slot];
    }

    /**
     * 模拟按下指定插槽对应的【关】按键
     */
    public void pressOffButton(int slot) {
        offCommands[slot].execute();
        undoCommand = offCommands[slot];
    }

    /**
     * 撤销功能
     */
    public void pressUndoButton() {
        undoCommand.undo();
    }

    @Override
    public String toString() {
        return "RemoteControl{" +
                "onCommands=" + Arrays.toString(onCommands) +
                ", offCommands=" + Arrays.toString(offCommands) +
                '}';
    }
}

クライアントの役割

リモートコントロールの取得、および照明、空調コマンド受信機を取得します。コマンド[OFF]、[それぞれ対応する開口を形成します]。
対応するスロットへのリンク。ボタンは、指定された命令のトリガーを押したとき。

package com.zero.headfirst.command;

import com.zero.headfirst.command.impl.*;
import com.zero.headfirst.command.receiver.AirConditioning;
import com.zero.headfirst.command.receiver.Light;
import com.zero.headfirst.command.receiver.Stereo;
import com.zero.headfirst.command.receiver.TV;

/**
 * 客户端角色
 */
public class CommandClient {
    public static void main(String[] args) {
        //创建一个遥控器-调用者角色
        RemoteControl remoteControl = new RemoteControl();
        //1. 创建电灯-接受者角色
        Light light = new Light();
        //创建开灯、关灯命令-命令具体角色
        LightOnCommand lightOnCommand = new LightOnCommand();
        lightOnCommand.setLight(light);
        LightOffCommand lightOffCommand = new LightOffCommand();
        lightOffCommand.setLight(light);

        //调用者设置电灯插槽以及对应的开关按键指令-调用者角色
        remoteControl.setCommand(0, lightOnCommand, lightOffCommand);

        // 2. 设置音响插槽与对应按键指令
        Stereo stereo = new Stereo();
        StereoOnCommand stereoOnCommand = new StereoOnCommand();
        stereoOnCommand.setStereo(stereo);
        StereoOffCommand stereoOffCommand = new StereoOffCommand();
        stereoOffCommand.setStereo(stereo);

        remoteControl.setCommand(1, stereoOnCommand, stereoOffCommand);

        //3. 空调
        AirConditioning airConditioning = new AirConditioning();
        AirConditioningOnCommand airConditioningOnCommand = new AirConditioningOnCommand();
        airConditioningOnCommand.setAirConditioning(airConditioning);
        AirConditioningOffCommand airConditioningOffCommand = new AirConditioningOffCommand();
        airConditioningOffCommand.setAirConditioning(airConditioning);

        remoteControl.setCommand(2, airConditioningOnCommand, airConditioningOffCommand);

        //4. 电视
        TV tv = new TV();
        TVOnCommand tvOnCommand = new TVOnCommand();
        tvOnCommand.setTv(tv);
        TVOffCommand tvOffCommand = new TVOffCommand();
        tvOffCommand.setTv(tv);

        remoteControl.setCommand(3, tvOnCommand, tvOffCommand);

        //模拟按键
        System.out.println("-------码农回家了,使用遥控开启电灯、音响、空调、电视----");
        remoteControl.pressOnButton(0);
        remoteControl.pressOnButton(1);
        remoteControl.pressOnButton(2);
        remoteControl.pressOnButton(3);

        System.out.println("------码农睡觉了,使用遥控关闭电灯、音响、电视。不关空调--------");
        remoteControl.pressOffButton(0);
        remoteControl.pressOffButton(1);
        remoteControl.pressOffButton(3);

        System.out.println("----撤销测试,先打开电灯。再关闭电灯。然后按撤销----");
        remoteControl.pressOnButton(0);
        remoteControl.pressOffButton(0);
        //一键撤销
        remoteControl.pressUndoButton();
    }
}

テスト結果

-------码农回家了,使用遥控开启电灯、音响、空调、电视----
打开电灯。
打开音响
放入CD
音响音量设置为20
打开空调
空调温度设置28°
打开电视
设置频道为宇宙电视台
电视音量设置为20
------码农睡觉了,使用遥控关闭电灯、音响、电视。不关空调--------
关灯。
关闭音响
关闭电视
----撤销测试,先打开电灯。再关闭电灯。然后按撤销----
打开电灯。
关灯。
打开电灯。

概要

使用シナリオ:

  1. 作業キュー:加算命令の一端は、オブジェクトがある限り、コマンドモードは、キューに入れることができるようにして達成されます。もう一方の端はスレッドです。キューからのコマンドを、コマンドを削除していき、その後コールがコマンドの後に廃棄され、メソッドが呼び出され、実行、および:スレッドは、次の作業を進めます。
  2. スレッドプール。

もっと世間の注目JavaStormモードはありません

ここに画像を挿入説明

公開された28元の記事 ウォンの賞賛2 ビュー1470

おすすめ

転載: blog.csdn.net/qq_14855971/article/details/92098100