Command設計模式和java回撥機制的異同
最大的區別在於命令模式的具體命令中組合了一個接收者物件,而java回撥機制中的介面的實現類中(即匿名內部類)中並沒有組合一個接收者,從而回調方法沒有繼續呼叫接收者的方法。簡而言之,java回撥機制相較command模式少了一層接收者環節。命令模式正是回撥機制的一個面向物件的替代品。
一、首先介紹回撥機制
回撥機制:一開始,一個類定義了一些個未實現的方法,並且該類並不知道這些方法具體的實現是怎麼樣的,因為只有等到執行時候才能夠知道這些方法的具體實現。等到具體要用到該類物件的時候,才對該類中的抽象方法定義實現。該實現的過程由client來實現。具體的程式碼如下所示:
回撥類
package需要呼叫callback的類callback; /** * 回撥介面 * * @author typ * */ public abstract class ICallBack { /** * 需要回調的方法。即在回撥時候需要實現的方法 */ public abstract void callback(); }
package callback; /** * 某個類需要呼叫回撥介面中的方法 * * @author typ * */ public class A { ICallBack iCallBack; /** * 在此處呼叫回撥介面時候,要先實現該介面 * * @param iCallBack */ public void setICallBack(ICallBack iCallBack) { this.iCallBack = iCallBack; } /** * 呼叫回撥介面中的方法,當然呼叫之前要先實現callback方法 */ public void doSomeThing() { iCallBack.callback(); } }
package callback; /** * 在執行的時候才能確定回撥方法的具體實現 * * @author typ * */ public class Client { public static void main(String[] args) { A a = new A(); a.setICallBack(new ICallBack() { /* 此處在建立ICallBack物件時候,定義callback函式的方法體 * (non-Javadoc) * @see callback.ICallBack#callback() */ public void callback() {system.out.println("A is running, and call back is running!"); } }); a.doSomeThing(); } }
二、command設計模式
命令模式是對命令的封裝。命令模式把發出命令的呼叫方和執行命令的接收方分割開,對兩者之間解耦。
每一個命令都是一個操作:呼叫方發出請求要求執行一個操作;接收方收到請求,並執行操作。如果沒有命令模式,那麼,呼叫方要存放一個接收方的引用,這樣增加了他們之間的耦合性。命令模式允許呼叫方和接收方獨立開來,使得呼叫方不必知道接收方的介面,更不必知道請求是怎麼被接收,以及操作是否被執行、何時被執行,以及是怎麼被執行的。並且利用command模式還可以執行redo和undo操作。程式碼走起:
命令接收方,其實最終還是接收方來執行命令
package command; /** * 命令的接收者 * * @author typ * */ public class Receiver { public void execute() { System.out.println("receiver is executing!"); } }
command抽象類,儲存一個指向接收方的引用,定義了一個execute方法,在子類中是想
package command; /** * 命令的抽象類,用於封裝不同型別的命令和接收者 * * @author typ * */ public abstract class Command { Receiver receiver; Command(Receiver receiver) { this.receiver = receiver; } public abstract void execute(); }
command的具體子類
package command; public class ConcreteCommand extends Command { ConcreteCommand(Receiver receiver) { super(receiver); } public void execute() { receiver.execute(); } }
呼叫方,儲存一個指向命令command的引用,可以傳入任何具體的command
package command; /** * 呼叫者 * * @author typ * */ public class Invoker { Command command; public Invoker() { } /** * 執行command */ public void invoke() { command.execute(); } public void setCommand(Command command) { this.command = command; } }
client測試類
package command; /** * 測試類 * * @author typ * */ public class Client { public static void main(String[] args) { Receiver receiver = new Receiver(); Command command = new ConcreteCommand(receiver); Invoker invoker = new Invoker(); invoker.setCommand(command); invoker.invoke(); } }
三、command模式如何替代回撥機制
"CallBack"講的便是先將一個函式登記上,然後在以後呼叫此函式。使用命令模式作為"CallBack"在面向物件系統中的替代。
下面我們就在回撥機制上面改,如下:
回撥類改為command類
package comm_call; /** * 回撥介面--相當於Command類 * * @author typ * */ public abstract class ICallBack { /** * 需要回調的方法。即在回撥時候需要實現的方法 */ public abstract void callback(); }
ICallBackImpl相當於ConcreteCommand
package comm_call; /** * ICallBack的實現類,這個類相當於Command的具體實現類ConcreteCommand * @author typ * */ public class ICallBackImpl extends ICallBack { public void callback() { System.out.println("A is running, and call back is running!"); } }
呼叫方類
package comm_call; /** * 該類作為呼叫方類 * * @author typ * */ public class A { ICallBack iCallBack; /** * 在此處呼叫回撥介面時候,要先實現該介面 * * @param iCallBack */ public void setICallBack(ICallBack iCallBack) { this.iCallBack = iCallBack; } /** * 呼叫回撥介面中的方法,當然呼叫之前要先實現callback方法 */ public void doSomeThing() { iCallBack.callback(); } }
測試類Client
package comm_call; /** * 在執行的時候傳入command物件,而不是實現回撥方法 * * @author typ * */ public class Client { public static void main(String[] args) { A a = new A(); ICallBackImpl iCallBackImpl = new ICallBackImpl(); // 此處傳入iCallBackImpl是一個命令的物件,回撥機制中此處傳入的是一個回撥類 a.setICallBack(iCallBackImpl); a.doSomeThing(); } }