2012-08-28 79 views
11

Command pattern可以用來實現Transactional behavior(和Undo)。
但我找不到這樣的一個例子,用谷歌搜索。我只能找到switched onoff燈的一些微不足道的例子。
我在哪裏可以找到使用Command Pattern實現的這些/這些行爲的編碼示例(最好在Java)?現實世界中應用命令模式的例子

回答

11

在我們的項目之一,我們有以下要求:

  1. 創建數據庫的記錄。
  2. 調用服務更新相關記錄。
  3. 調用另一項服務來記錄票證。

要以事務處理方式執行此操作,每個操作都將作爲具有撤消操作的命令來實現。在每個步驟結束時,命令被壓入堆棧。如果操作在某個步驟中失敗,那麼我們彈出堆棧中的命令,並在彈出的每個命令上調用undo操作。每個步驟的撤消操作都是在該命令實現中定義的,以反轉早期的command.execute()。

希望這會有所幫助。

+0

不知道我關注。一個事務被rollbacked.Is不是由撤消操作組成的。你是如何用命令模式實現原子部分的? – Jim

+0

在數據庫級事務中,每個操作都是具有撤消和重做操作的命令。在回滾時,DBMS將調用撤銷操作來恢復對其所保存的數據庫副本所做的更改。我們在跨系統的分佈式事務中模擬同樣的事情。這現在有道理嗎? – Vikdor

+0

'恢復對其保存的數據庫副本所做的更改'。因此該命令首先應用於數據副本而不是實際數據?我認爲它直接應用於數據,這就是爲什麼您需要'撤銷'。你的描述有點清晰,但我需要更多的底層細節,如果可能的話可以看到大圖 – Jim

2
public final class Ping implements Callable<Boolean> { 

    private final InetAddress peer; 

    public Ping(final InetAddress peer) { 
    this.peer = peer; 
    } 

    public Boolean call() { 
    /* do the ping */ 
    ... 
    } 
} 
... 
final Future<Boolean> result 
    = executorService.submit(new Ping(InetAddress.getByName("google.com"))); 
System.out.println("google.com is " + (result.get() ? "UP" : "DOWN")); 
+5

這個例子是什麼? – Jim

+0

@Jim關於模式的維基百科文章明確指出以下內容......「*一個典型的通用線程池類可能有一個公共的'addTask'方法,它將工作項添加到等待完成的任務的內部隊列中。...隊列中的項目是命令對象,通常這些對象實現一個通用接口,例如'java.lang.Runnable',它允許線程池執行命令,即使線程池類本身沒有任何知識*「 – oldrinb

+0

@Jim這是Java中的一個例子,除了使用'Callable'而不是'Runnable'和['ExecutorService'](http:// docs。 oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html)。在關於維基百科文章本身的討論中可以看到類似的例子(這裏是http://en.wikipedia.org/wiki/Talk%3ACommand_pattern#Python_examples)。 – oldrinb

1

命令模式被用在很多地方。

  1. 當然你到處看到的是GUI實現的一個非常簡單的例子,開關。它也廣泛用於遊戲開發。使用這種模式,用戶也可以在屏幕上配置他的按鈕。
  2. 它也用於網絡,如果命令必須傳遞到另一端。
  3. 當程序員想存儲用戶執行的所有命令時,例如有時候一款遊戲可以讓你重播整個關卡。
  4. 它用於實現回調。

這裏是一個網站,它提供了一個用於回調的命令模式的例子。 http://www.javaworld.com/article/2077569/core-java/java-tip-68--learn-how-to-implement-the-command-pattern-in-java.html?page=2

  1. 這是另一個顯示數據庫命令模式的鏈接。代碼是用C#編寫的。 http://www.codeproject.com/Articles/154606/Command-Pattern-at-Work-in-a-Database-Application
0

You have to define undo(), redo() operations along with execute() in Command interface itself

例如:

interface ChangeI { 
    enum State{ READY, DONE, UNDONE, STUCK } ; 
    State getState() ; 

    void execute() ;  
    void undo() ;  
    void redo() ; 
} 

ConcreteCommand類中定義的國家。取決於execute()方法後的當前狀態,您必須決定是否應將命令添加到Undo StackRedo Stack並相應地作出決定。

abstract class AbstractChange implements ChangeI { 
    State state = State.READY ; 

    public State getState() { return state ; } 

    public void execute() { 
     assert state == State.READY ; 
     try { doHook() ; state = State.DONE ; } 
     catch(Failure e) { state = State.STUCK ; } 
     catch(Throwable e) { assert false ; } 
    } 

    public void undo() { 
     assert state == State.DONE ; } 
     try { undoHook() ; state = State.UNDONE ; } 
     catch(Failure e) { state = State.STUCK ; } 
     catch(Throwable e) { assert false ; } 
    } 

    public void redo() { 
     assert state == State.UNDONE ; 
     try { redoHook() ; state = State.DONE ; } 
     catch(Failure e) { state = State.STUCK ; } 
     catch(Throwable e) { assert false ; } 
    } 

    protected abstract void doHook() throws Failure ; 

    protected abstract void undoHook() throws Failure ; 

    protected void redoHook() throws Failure { doHook() ;} ; 
} 

看看這個undo-redo命令文章,以便更好地理解。