命令模式/Command

命令模式/Command

意圖/適用場景:
命令模式是對命令的封裝。命令模式把發出命令的責任和執行命令的責任分割開,委派給不同的對象。
每一個命令都是一個操作:請求的一方發出請求要求執行一個操作;接收的一方收到請求,並執行操作。命令模式允許請求的一方和接收的一方獨立開來,使得請求的一方不必知道接收請求的一方的接口,更不必知道請求是被誰處理、是否被處理、何時處理以及怎麼處理。
命令模式有以下的優點:

  1. 允許請求方與接收方能夠獨立演化,使它們完全沒有關係,只需要面向命令就可以了;
  2. 命令本身也容易演化,新的命令容易被加入系統;
  3. 接收請求的一方靈活性很大,可以選擇接收與否,以及決定處理的細節;
  4. 容易設計一個命令隊列;
  5. 可以容易地實現命令歷史/日誌功能。

UML:

命令模式/Command

參與者:

  1. 命令(Command):所有命令的抽象接口。
  2. 具體命令(ConcreteCommand):定義命令的具體內容。
  3. 遞送者(Deliverer):負責命令的遞送過程。它從請求者那裏接收命令,並把命令分發到合適的地方去。這一角色的靈活性比較大,它可以維護一個命令隊列,可以記錄命令歷史。
  4. 請求者(Invoker):命令的來源。
  5. 接收者(Receiver):所有命令處理器的抽象接口。
  6. 具體接收者(ConcreteReceiver):具體化Receiver接口,實現處理命令的具體功能。

要點:
這裏描述的命令模式與《Java與模式》和《設計模式》中描述的命令者不大相同。
命令模式最關鍵的概念是把請求者、接收者以及命令三方解耦合,但這兩本書中所定義的模式結構以及給出的示例代碼不夠好。
這兩書中實例的好處在於從結構上把三方解耦,每一個角色都可以面向接口編程,在實現進有很大的選擇空間。
但是,它們互相之間仍然互相引用,不能說是完全解耦。一個更好的方法是引入一個遞送者角色,它負責命令的分發以及隊列的維護。這樣,三方者不需要再互相引用。而且在時序上看,可以做到異步遞送,擴展了系統的功能。

應用實例:
這種命令/消息式的實例實在是太多。
還是看AWT的事件模式,在責任鏈模式裏就講過,一個事件產生後,會被依次分發給各個Listener去嘗試處理,直到找到一個合適的處理者。
這裏,可以想象有一個事件處理器,即Deliverer;產生事件的構件就是Invoker,它把事件交給Deliverer,就不再過問這個事件的處理過程了;Deliverer把事件交給第一個監聽,也就是本模式中的Receiver,如果Receiver在handleEvent()中返回false,Deliverer還需要再找下一個Receiver。

示例代碼:

   [java]
// Source code from file:  ConcreteReceiver.java

package designPatterns.Command;

public class ConcreteReceiver implements Receiver {
public void handle(Event e) {
System.out.println("ConcreteReceiver.handle()");
}
}

// Source code from file:  Deliverer.java

package designPatterns.Command;

public class Deliverer extends Thread {

// This simulate a event queue, the length of the queue is 1 here.
private Event queue = null;
private Receiver receiver = null;

public Deliverer(Receiver receiver) {
this.receiver = receiver;
}

public void deliver(Event e) {
queue = e;
}

public void distribute(Event e) {
receiver.handle(e);
}

public void run() {
int count = 3;
while (count-- > 0) {
try {
sleep(1000);
if (null != queue) {
distribute(queue);
queue = null;
}
catch (Exception e) {}
}
}
}

// Source code from file:  Event.java

package designPatterns.Command;

public class Event {
int type;
int parameterA;
int parameterB;
}

// Source code from file:  Invoker.java

package designPatterns.Command;

public class Invoker {

Deliverer deliverer = null;

public Invoker(Deliverer deliverer) {
this.deliverer = deliverer;
}

public void act() {
Event e = new Event();
deliverer.deliver(e);
}
}

// Source code from file:  Receiver.java

package designPatterns.Command;

public interface Receiver {
public void handle(Event e);
}

// Source code from file:  User.java

package designPatterns.Command;

public class User {
public static void main(String[] args) {
Receiver receiver = new ConcreteReceiver();
Deliverer deliverer = new Deliverer(receiver);
deliverer.start();
Invoker invoker = new Invoker(deliverer);
invoker.act();
}
}
[/java]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章