研磨設計模式之命令模式 3

2021-08-25 07:12:49 字數 3907 閱讀 5871

可撤銷操作的意思就是:放棄該操作,回到未執行該操作前的狀態。這個功能是乙個非常重要的功能,幾乎所有gui應用裡面都有撤消操作的功能。gui的選單是命令模式最典型的應用之一,所以你總是能在選單上找到撤銷這樣的選單項。

既然這麼常用,那該如何實現呢?

有兩種基本的思路來實現可撤銷的操作,一種是補償式,又稱反操作式:比如被撤銷的操作是加的功能,那撤消的實現就變成減的功能;同理被撤銷的操作是開啟的功能,那麼撤銷的實現就變成關閉的功能。

另外一種方式是儲存恢復式,意思就是把操作前的狀態記錄下來,然後要撤銷操作的時候就直接恢復回去就可以了。

這裡先講第一種方式,就是補償式或者反操作式,第二種方式放到備忘錄模式中去講解。為了讓大家更好的理解可撤銷操作的功能,還是用乙個例子來說明會比較清楚。

1:範例需求

考慮乙個計算器的功能,最簡單的那種,只能實現加減法運算,現在要讓這個計算器支援可撤銷的操作。

2:補償式或者反操作式的解決方案

(1)在實現命令介面之前,先來定義真正實現計算的介面,沒有它命令什麼都做不了,操作運算的介面的示例**如下:

/**

* 操作運算的介面

*/public inte***ce operationapi

定義了介面,來看看真正執行加減法的實現,示例**如下:

/**

* 運算類,真正實現加減法運算

*/public class operation implements operationapi

public void setresult(int result)public void add(int num)

public void substract(int num)}

(2)接下來,來抽象命令介面,由於要支援可撤銷的功能,所以除了跟前面一樣定義乙個執行方法外,還需要定義乙個撤銷操作的方法,示例**如下:

/**

* 命令介面,宣告執行的操作,支援可撤銷操作

*/public inte***ce command

(3)應該來實現命令了,具體的命令分成了加法命令和減法命令,先來看看加法命令的實現,示例**如下:

/**

* 具體的加法命令實現物件

*/public class addcommand implements command

public void undo() /**

* 構造方法,傳入具體執行計算的物件

* @param operation 具體執行計算的物件

* @param openum 要加上的資料

*/public addcommand(operationapi operation,int openum)

}

減法命令和加法類似,只是在實現的時候和加法反過來了,示例**如下:

/**

* 具體的減法命令實現物件

*/public class substractcommand implements commandpublic void execute()

public void undo()}

(4)接下來應該看看計算器了,計算器就相當於invoker,持有多個命令物件,計算器是實現可撤銷操作的地方。

為了大家更好的理解可撤銷的功能,先來看看不加可撤銷操作的計算器類什麼樣子,然後再新增上可撤銷的功能示例。示例**如下:

/**

* 計算器類,計算器上有加法按鈕、減法按鈕

*/public class calculator

/*** 設定執行減法的命令物件

* @param substractcmd 執行減法的命令物件

*/public void setsubstractcmd(command substractcmd)

/*** 提供給客戶使用,執行加法功能

*/public void addpressed()

/*** 提供給客戶使用,執行減法功能

*/public void substractpressed()

}

目前看起來跟前面的例子實現得差不多,現在就在這個基本的實現上來新增可撤銷操作的功能。

要想實現可撤銷操作,首先就需要把操作過的命令記錄下來,形成命令的歷史列表,撤銷的時候就從最後乙個開始執行撤銷。因此我們先在計算器類裡面加上命令歷史列表,示例**如下:

/**

* 命令的操作的歷史記錄,在撤銷時候用

*/private listundocmds = new arraylist();

什麼時候向命令的歷史記錄裡面加值呢?

很簡單,答案是在每個操作按鈕被按下的時候,也就是你操作加法按鈕或者減法按鈕的時候,示例**如下

public void addpressed()

public void substractpressed()

然後在計算器類裡面新增上乙個撤銷的按鈕,如果它被按下,那麼就從命令歷史記錄裡取出最後乙個命令來撤銷,撤消完成後要把已經撤銷的命令從歷史記錄裡面刪除掉,相當於沒有執行過該命令了,示例**如下:

public void undopressed()else

}

同樣的方式,還可以實現恢復的功能,也為恢復設定乙個可恢復的列表,需要恢復的時候從列表裡面取最後乙個命令進行重新執行就好了,示例**如下:

/**

* 命令被撤銷的歷史記錄,在恢復時候用

*/private listredocmds = new arraylist();

那麼什麼時候向這個集合裡面賦值呢?大家要注意,恢復的命令資料是**於撤銷的命令,也就是說有撤銷才會有恢復,所以在撤銷的時候向這個集合裡面賦值,注意要在撤銷的命令被刪除前賦值。示例**如下:

public void undopressed()else

}

那麼如何實現恢復呢?請看示例**:

public void redopressed()else

}

/**

* 計算器類,計算器上有加法按鈕、減法按鈕,還有撤銷和恢復的按鈕

*/public class calculator

public void setsubstractcmd(command substractcmd)

public void addpressed()

public void substractpressed()

public void undopressed()else

} public void redopressed()else

}}

(5)終於到可以收穫的時候了,寫個客戶端,組裝好命令和接收者,然後操作幾次命令,來測試一下撤銷和恢復的功能,示例**如下:

public class client 

}

(6)執行一下,看看結果,享受一下可以撤銷和恢復的操作,結果如下:

一次加法運算後的結果為:5

一次減法運算後的結果為:2

撤銷一次後的結果為:5

再撤銷一次後的結果為:0

恢復操作一次後的結果為:5

再恢復操作一次後的結果為:2

也就是初始值為0,執行的兩次命令操作為先加上5,然後再減去3。看起來也很容易,對不。

未完待續......

研磨設計模式之工廠方法模式 3

1 模式的功能 工廠方法的主要功能是讓父類在不知道具體實現的情況下,完成自身的功能呼叫,而具體的實現延遲到子類來實現。這樣在設計的時候,不用去考慮具體的實現,需要某個物件,把它通過工廠方法返回就好了,在使用這些物件實現功能的時候還是通過介面來操作,這非常類似於ioc di的思想,這個在後面給大家稍詳...

研磨設計模式之裝飾模式 1

考慮這樣乙個實際應用 就是如何實現靈活的獎金計算。獎金計算是相對複雜的功能,尤其是對於業務部門的獎金計算方式,是非常複雜的,除了業務功能複雜外,另外乙個麻煩之處是計算方式還經常需要變動,因為業務部門經常通過調整獎金的計算方式來激勵士氣。先從業務上看看現有的獎金計算方式的複雜性 看了上面獎金計算的問題...

研磨設計模式之橋接模式 1

來寫乙個大家既陌生又熟悉的設計模式,也是非常實用的乙個設計模式,那就是橋接模式。說陌生是很多朋友並不熟悉這個設計模式,說熟悉是很多人經常見到或者是下意識的用到這個設計模式,只是不知道罷了。橋接模式是非常實用的乙個模式,下面就來寫寫它。考慮這樣乙個實際的業務功能 傳送提示訊息。基本上所有帶業務流程處理...