nit*_*.kk 6 java design-patterns command-pattern
Command 模式有一个 IReceiver 接口,其中有几个方法,并且与每个方法相对应,有具体的 Command 对象(实现一个接口ICommand
)。
我读到客户端知道具体接收器和具体命令,并且通常是客户端在具体命令对象中设置接收器对象。那为什么说它解耦了发送者和接收者呢?
当客户端已经知道具体的接收者时,我觉得这不是松耦合,而且在这种情况下客户端可以直接调用接收者对象上的 API(方法)。
您可以将命令模式工作流程视为如下。
Command
为所有命令声明一个接口,提供一个简单的execute()方法,要求命令的接收者执行操作。
他们Receiver
知道如何执行请求。
持有Invoker
一个命令,可以Command
通过调用execute方法来执行请求。
创建并设置命令的a Client
。ConcreteCommands
Receiver
定义ConcreteCommand
了动作和接收者之间的绑定。
当Invoker
调用执行时ConcreteCommand
,将在接收器上运行一项或多项操作。
查看示例代码以更好地理解事物。
public class CommandDemoEx{
public static void main(String args[]){
// On command for TV with same invoker
Receiver r = new TV();
Command onCommand = new OnCommand(r);
Invoker invoker = new Invoker(onCommand);
invoker.execute();
// On command for DVDPlayer with same invoker
r = new DVDPlayer();
onCommand = new OnCommand(r);
invoker = new Invoker(onCommand);
invoker.execute();
}
}
interface Command {
public void execute();
}
class Receiver {
public void switchOn(){
System.out.println("Switch on from:"+this.getClass().getSimpleName());
}
}
class OnCommand implements Command{
private Receiver receiver;
public OnCommand(Receiver receiver){
this.receiver = receiver;
}
public void execute(){
receiver.switchOn();
}
}
class Invoker {
public Command command;
public Invoker(Command c){
this.command=c;
}
public void execute(){
this.command.execute();
}
}
class TV extends Receiver{
public TV(){
}
public String toString(){
return this.getClass().getSimpleName();
}
}
class DVDPlayer extends Receiver{
public DVDPlayer(){
}
public String toString(){
return this.getClass().getSimpleName();
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
java CommandDemoEx
Switch on from:TV
Switch on from:DVDPlayer
Run Code Online (Sandbox Code Playgroud)
回答你的问题:
我读过客户端了解具体接收器和具体命令,通常是客户端在具体命令对象中设置接收器对象。那为什么说它解耦了发送者和接收者
为了标准化词语,请将“发送者”替换为“调用者”。现在看一下代码。
Invoker simply executes the ConcreteCommand
(本例中为 OnCommand)通过传递 ConcreteReceiver。ConcreteCommand executes Command
通过ConcreteReceiver即ConcreteCommand defines binding between Action and Receiver.
execute()
Invoker的方法中添加业务逻辑,如java.lang.Thread,这已经解释如下。Client (sender) and Receiver are loosely couple through Invoker, which has knowledge of what command to be executed
。此链接中的线程示例
您可以通过实现 Runnable 对象来创建线程。
Thread t = new Thread (new MyRunnable()).start();
Run Code Online (Sandbox Code Playgroud)
=>
Invoker invoker = new Invoker(new ConcreteCommand());
invoker.start()
Run Code Online (Sandbox Code Playgroud)
并且您在 start() 中有逻辑来调用 ConcreteCommand.execute() ,在上面的情况下是 run() 。
start()方法会调用Thread中的run()方法。如果直接调用run()方法会发生什么?它不会被视为线程。
与该线程的start()方法一样,您可以在Invoker中添加一些业务逻辑。
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
start0();
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}
private native void start0(); // Native code is not here but this method will call run() method
public void run() {
if (target != null) {
target.run();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
在您的最后一个查询中
这里我们创建了命令对象、接收者对象和调用者对象。然后将接收者对象传递给命令对象,然后将命令对象传递给调用者对象。我们为每个接收器执行此操作,就像我们在此处为电视和 DVD 播放器执行的操作一样。此外,在方法中,TV 和 DVDPlayer 的“主”对象是已知的并且实际上是被创建的。我们可以简单地执行 tvObject.switchOn() 和 dvdPlayer.switchOn()。命令模式有何帮助
客户无需担心Receiver
班级的变化。Invoker
直接作用于ConcreteCommand
,它有Receiver
对象。Receiver
对象将来可能会siwtchOn
从 ()变为 ()。switchOnDevice
但客户端交互并没有改变。
如果您有两个不同的命令,例如switchOn
() 和switchOff
(),您仍然可以使用相同的Invoker
.
归档时间: |
|
查看次数: |
3004 次 |
最近记录: |