命令模式如何使发送者与接收者分离? [英] How does the Command pattern decouple the sender from the receiver?

查看:120
本文介绍了命令模式如何使发送者与接收者分离?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

命令模式具有几个方法的IReceiver接口,对应于每个方法,具体的Command对象(使用execute()方法实现一个接口 ICommand )。



我已经看到客户端知道具体的接收者和具体命令,通常客户端在具体的命令对象中设置接收者对象。那么为什么说它解耦发送者和接收者?



当客户端已经知道具体的接收者时,我觉得这不是松散的耦合,而且客户端在这个case可以直接调用接收器对象上的API(方法)。

解决方案

/ p>


  1. 命令为所有命令声明一个接口,提供一个简单的执行)方法,要求接收方执行命令。


  2. Receiver 具有知道如何执行请求。


  3. Invoker 持有一个命令,可以得到 c code code code code code code code code code $客户端创建 ConcreteCommands 并为命令设置 Receiver


  4. ConcreteComman d 定义了操作和接收者之间的绑定。


  5. Invoker 调用执行 ConcreteCommand 将在Receiver上运行一个或多个操作。


查看示例代码以更好的方式了解事情。

  public class CommandDemoEx {
public static void main(String args []){

// On with with with with invoker
Receiver r = new TV();
命令onCommand = new OnCommand(r);
Invoker invoker = new Invoker(onCommand);
invoker.execute();

//对于具有相同调用者的DVDPlayer的命令
r = new DVDPlayer();
onCommand = new OnCommand(r);
invoker = new Invoker(onCommand);
invoker.execute();

}
}
接口命令{
public void execute();
}

class Receiver {
public void switchOn(){
System.out.println(从...启动+ this.getClass()。getSimpleName ());
}
}

class OnCommand实现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();
}
}

输出:

  java CommandDemoEx 
打开电话:TV
从:打开DVDPlayer

要回答您的问题:


我已经阅读了客户端了解具体的接收者具体命令,通常是客户端在具体的命令对象中设置接收者对象。那么为什么说它解耦发送者和接收者


要标准化这些单词,将sender替换为invoker。现在看看代码。


  1. Invoker只需执行ConcreteCommand (OnCommand在这种情况下)通过传递ConcreteReceiver。

  2. ConcreteCommand通过ConcreteReceiver执行命令 ,即 ConcreteCommand定义Action和Receiver之间的绑定。

  3. 如果看到工作流,Invoker不会随其他命令而改变,您可以在 execute() Invoker的方法,如java.lang.Thread,已解释如下。

  4. 这样 code>客户端(发件人)和Receiver通过Invoker松散耦合,Invoker知道要执行什么命令

线程示例 从这个链接



您可以通过实现Runnable对象来创建线程。

 线程t =新线程(新的MyRunnable())。开始(); 

=>

 code> Invoker invoker = new Invoker(new ConcreteCommand()); 
invoker.start()

你有start()到在上述情况下调用ConcreteCommand.execute(),它是run()。



start()方法将调用run在线程。如果直接直接调用run()方法会怎么样?它不会被视为线程



像这个线程的start()方法一样,您可以在Invoker中添加一些业务逻辑。

  public synchronized void start(){
/ **
*此方法未被调用主方法线程或系统
*由VM创建/设置的组线程。将来向此方法添加
*的任何新功能也可能还要添加到VM中。
*
*零状态值对应于状态NEW。
* /
if(threadStatus!= 0)
throw new IllegalThreadStateException();
group.add(this);
start0();
if(stopBeforeStart){
stop0(throwableFromStop);
}
}

private native void start0(); //本地代码不在这里,但是这个方法会调用run()方法

public void run(){
if(target!= null){
target.run );
}
}

编辑:



在上次查询


这里我们正在创建命令对象,Receiver对象和Invoker Object。然后在命令对象中传递接收方对象,然后在invoker对象中传递命令对象。我们为每个接收机做的就像我们在这里做电视和DVDPlayer。在电视和DVDPlayer的方法main对象中也是已知的,实际上是创建的。我们可以简单地做tvObject.switchOn()和dvdPlayer.switchOn()。命令模式如何帮助


客户端不必担心 Receiver 类中的更改。 Invoker 直接在 ConcreteCommand 上工作,其中有 Receiver 对象。 接收者对象可能会将 siwtchOn ()更改为 switchOnDevice ()在未来。但客户互动并不会改变。



如果您有两个不同的命令,如 switchOn ()和 switchOff (),仍然可以使用相同的 Invoker


The Command pattern has an IReceiver interface with few methods and corresponding to each method there are concrete Command objects (implementing an interface ICommand with execute() method).

I have read that the client knows about the concrete receiver and concrete command and it is usually the client setting up the receiver object in the concrete command object. Then why it is said it decouples the sender and the receiver?

When the client already knows the concrete receiver then I feel this is not loose coupling and also the client in this case can directly call the APIs (methods) on the receiver object.

解决方案

You can think of Command pattern workflow as follows.

  1. Command declares an interface for all commands, providing a simple execute() method which asks the Receiver of the command to carry out an operation.

  2. The Receiver has the knowledge of what to do to carry out the request.

  3. The Invoker holds a command and can get the Command to execute a request by calling the execute method.

  4. The Client creates ConcreteCommands and sets a Receiver for the command.

  5. The ConcreteCommand defines a binding between the action and the receiver.

  6. When the Invoker calls execute the ConcreteCommand will run one or more actions on the Receiver.

Have a look at sample code to understand things in better way.

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();
    }
}

output:

java CommandDemoEx
Switch on from:TV
Switch on from:DVDPlayer

To answer your question :

I have read client knows about the concrete receiver and concrete command and it is usually client setting up the receiver object in the concrete command object. Then why it is said it decouples the sender and the receiver

To standardize the words, replace "sender" with "invoker". Now go through the code.

  1. Invoker simply executes the ConcreteCommand (OnCommand in this case) by passing ConcreteReceiver.
  2. ConcreteCommand executes Command through ConcreteReceiver i.e. ConcreteCommand defines binding between Action and Receiver.
  3. If you see the workflow, Invoker does not change with additional commands and you can add business logic in execute() method of Invoker like java.lang.Thread, which has been explained as below.
  4. In this way Client (sender) and Receiver are loosely couple through Invoker, which has knowledge of what command to be executed.

Thread example from this link

You can create Thread by implementing Runnable object.

Thread t = new Thread (new MyRunnable()).start();

=>

 Invoker invoker = new Invoker(new ConcreteCommand());
 invoker.start() 

and you have logic in start() to call ConcreteCommand.execute() which is run() in above case.

start() method will call run() method in Thread. What happens if you directly call run() method directly? It won't be treated as thread.

Like start() method of this thread, you can add some business logic in 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();
    }
}

EDIT:

On your last query

Here we are creating the command object, Receiver object and Invoker Object.Then passing the receiver object in the command object and then passing the command object in invoker object. This we do for each Receiver like we do here for TV and DVDPlayer. Also in the method 'main' Object of TV and DVDPlayer are known and in fact are created. We can simply do tvObject.switchOn() and dvdPlayer.switchOn(). How does Command pattern help

Client need not worry about changes in Receiver class. Invoker directly works on ConcreteCommand, which has Receiver object. Receiver object may change siwtchOn() to switchOnDevice() in future. But client interaction does not change.

If you have two different commands like switchOn() and switchOff(), still you can use same Invoker.

这篇关于命令模式如何使发送者与接收者分离?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆