Command模式(指令) Java深入到一定程度,就不可避免的碰到設計模式這一概念,了解設計模式,将使自己對java中的接口或抽象類應用有更深的了解.設計模式在java的中型系統中應用廣泛,遵循一定的程式設計模式,才能使自己的代碼便于了解,易于交流,Command(指令模式)模式是比較常用的一個模式.
Command指令模式:Command模式通過被稱為Command的類封裝了對目标對象的調用行為以及調用參數。将一個請求封裝為一個對象,進而使你不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支援可撤銷的操作。
優點:解耦了調用者和接受者之間聯系。調用者調用一個操作,接受者接受請求執行相應的動作,因為使用Command模式解耦,調用者無需知道接受者任何接口。
缺點:造成出現過多的具體指令類
在此寫了7個java類來描述說明Command設計模式的實作方式;
1、Control.java 指令控制者對象類
2、Tv.java 指令接收者對象類
3、Command.java 指令接口類
4、CommandChannel.java 頻道切換指令類
5、CommandOff.java 關機指令類
6、CommandOn.java 開機指令類
7、CommandTest.java 帶有main方法的測試類(指令發送者)
=============== 1、 Control.java
package command;
//指令控制者
public class Control {
private Command onCommand, offCommand,changeChannel;
public Control(Command on, Commandoff, Command channel) {
onCommand = on;
offCommand = off;
changeChannel = channel;
}
public void turnOn() {
onCommand.execute();
}
public void turnOff() {
offCommand.execute();
}
public void changeChannel() {
changeChannel.execute();
}
}
=============== 1end
=============== 2、 Tv.java
package command;
//指令接收者
public class Tv {
public int currentChannel = 0;
public void turnOn() {
System.out.println("The televisino is on.");
}
public void turnOff() {
System.out.println("The television is off.");
}
public void changeChannel(int channel){
this.currentChannel = channel;
System.out.println("Now TV channel is " + channel);
}
}
=============== 2end
=============== 3、 Command.java
package command;
//指令接口
public interface Command {
void execute();
}
=============== 3end
=============== 4、 CommandChannel.java
package command;
//頻道切換指令
public class CommandChannel implements Command {
private Tv myTv;
private int channel;
public CommandChannel(Tv tv, intchannel) {
myTv = tv;
this.channel = channel;
}
public void execute() {
myTv.changeChannel(channel);
}
}
=============== 4end
=============== 5、 CommandOff.java
package command;
//關機指令
public class CommandOff implements Command {
private Tv myTv;
public CommandOff(Tv tv) {
myTv = tv;
}
public void execute() {
myTv.turnOff();
}
}
=============== 5end
=============== 6、 CommandOn.java
package command;
//開機指令
public class CommandOn implements Command {
private Tv myTv;
public CommandOn(Tv tv) {
myTv = tv;
}
public void execute() {
myTv.turnOn();
}
}
=============== 6end
=============== 7、 CommandTest.java
package command;
//指令發送者
public class CommandTest{
public static void main(String[]args){
//指令接收者
Tv myTv = new Tv();
//開機指令
CommandOn on = new CommandOn(myTv);
//關機指令
CommandOff off = new CommandOff(myTv);
//頻道切換指令
CommandChannel channel = new CommandChannel(myTv, 2);
//指令控制對象
Control control = new Control( on, off, channel);
//開機
control.turnOn();
//切換頻道
control.changeChannel();
//關機
control.turnOff();
}
}
=============== 7end
Command模式通常可應用到以下場景:
1 Multi-levelundo(多級undo操作)
如果系統需要實作多級回退操作,這時如果所有使用者的操作都以command對象的形式實作,系統可以簡
單地用stack來儲存最近執行的指令,如果使用者需要執行undo操作,系統隻需簡單地popup一個最近的
command對象然後執行它的undo()方法既可。
2 Transactionalbehavior(原子事務行為)
借助command模式,可以簡單地實作一個具有原子事務的行為。當一個事務失敗時,往往需要回退到執
行前的狀态,可以借助command對象儲存這種狀态,簡單地處理回退操作。
3 Progressbars(狀态條)
假如系統需要按順序執行一系列的指令操作,如果每個command對象都提供一個
getEstimatedDuration()方法,那麼系統可以簡單地評估執行狀态并顯示出合适的狀态條。
4 Wizards(導航)
通常一個使用多個wizard頁面來共同完成一個簡單動作。一個自然的方法是使用一個command對象來封
裝wizard過程,該command對象在第一個wizard頁面顯示時被建立,每個wizard頁面接收使用者輸入并設
置到該command對象中,當最後一個wizard頁面使用者按下“Finish”按鈕時,可以簡單地觸發一個事件
調用execute()方法執行整個動作。通過這種方法,command類不包含任何跟使用者界面有關的代碼,可以
分離使用者界面與具體的處理邏輯。
5 GUI buttons andmenu items(GUI按鈕與菜單條等等)
Swing系統裡,使用者可以通過工具條按鈕,菜單按鈕執行指令,可以用command對象來封裝指令的執行。
6 Threadpools(線程池)
通常一個典型的線程池實作類可能有一個名為addTask()的public方法,用來添加一項工作任務到任務
隊列中。該任務隊列中的所有任務可以用command對象來封裝,通常這些command對象會實作一個通用的
接口比如java.lang.Runnable。
7 Macrorecording(宏紀錄)
可以用command對象來封裝使用者的一個操作,這樣系統可以簡單通過隊列儲存一系列的command對象的狀
态就可以記錄使用者的連續操作。這樣通過執行隊列中的command對象,就可以完成"Play back"操作了。
8 Networking
通過網絡發送command指令到其他機器上運作。
9 ParallelProcessing(并發處理)
當一個調用共享某個資源并被多個線程并發處理時。
執行個體二:
package command2;
public class AddRequirementCommand extends Command {
//執行增加一項需求的指令
public void execute() {
//找到需求組
super.rg.find();
//增加一份需求
super.rg.add();
//給出計劃
super.rg.plan();
}
}
----------------------------------------------------------
package command2;
public class Client {
public static void main(String[] args) {
//定義我們的接頭人
Invoker xiaoSan = newInvoker(); //接頭人就是我小三
//客戶要求增加一項需求
System.out.println("-------------客戶要求增加一項需求-----------------");
//客戶給我們下指令來
Command command = newAddRequirementCommand();
//接頭人接收到指令
xiaoSan.setCommand(command);
//接頭人執行指令
xiaoSan.action();
}
}
------------------------------------------------------------------
package command2;
public class CodeGroup extends Group {
//客戶要求代碼組過去和他們談
public void find() {
System.out.println("找到代碼組...");
}
//客戶要求增加一項功能
public void add() {
System.out.println("客戶要求增加一項功能...");
}
//客戶要求修改一項功能
public void change() {