Java设计模式之命令模式(Command Pattern)

介绍


命令模式是一种行为型设计模式,它是降低类之间耦合度的一种方式。命令模式中,将每个具体操作封装成一个个命令,调用者只需要发出特定的命令即可实现相应的功能。各个命令类会自动找到实现这个功能的对象并调用它们的方法。下面先来看一下命令模式的定义:

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

一般而言,一个命令会涉及到多个对象,为了避免调用者依赖这么多对象,命令模式将各种命令封装好后交给调用者,命令内部高内聚,外部低耦合,非常符合设计模式的原则。

命令模式一般包含三种角色:

  • Receive接收者。命令类调用各个接收者的方法来执行相应的命令,接收者是命令的执行者。
  • Command命令类。将调用者需要使用的命令封装好就是命令类,底层实现是调用各个接收者的方法。
  • Invoker调用者。调用者负责接收命令,命令发布者只和调用者进行通信,不依赖其他对象,将命令传给调用者,调用者负责执行。

例子


如果我现在要让一只小猫和一只小狗执行一些特定的命令,我并不直接对小猫和小狗说,而是将命令传给调用者,由调用者去执行。下面看一下具体代码实现:

抽象命令接收者:

public abstract class Receiver {
    public abstract void walk();
    public abstract void sit();
}

具体命令接收者就是小猫和小狗。

小猫:

public class Cat extends Receiver {
    @Override
    public void walk() {
        System.out.println("猫在走...");
    }
    @Override
    public void sit() {
        System.out.println("猫坐下了...");
    }
}

小狗:

public class Dog extends Receiver {
    @Override
    public void walk() {
        System.out.println("狗在走...");
    }
    @Override
    public void sit() {
        System.out.println("狗坐下了...");
    }
}

命令接收者定义好后,就是命令类了。

抽象命令类:

public abstract class Command {
    protected Receiver receiver1;
    protected Receiver receiver2;
    public abstract void execute();
    public void setReceiver(Receiver receiver1, Receiver receiver2) {
        this.receiver1 = receiver1;
        this.receiver2 = receiver2;
    }
}

具体命令类:

走:

public class WalkCommand extends Command {
    @Override
    public void execute() {
        super.receiver1.walk();
        super.receiver2.walk();
    }
}

坐下:

public class SitCommand extends Command {
    @Override
    public void execute() {
        super.receiver1.sit();
        super.receiver2.sit();
    }
}

最后是我们的调用者:

public class Invoker {
    private Command com;

    public void setCommand(Command com) {
        this.com = com;
    }

    public void action() {
        this.com.execute();
    }
}

OK,现在三大角色已经定义好了,最后测试一下:

//命令调用者。
Invoker invoker = new Invoker();
//命令执行者(猫和狗)。
Receiver cat = new Cat();
Receiver dog = new Dog();
//命令。
System.out.println("开始走------------");
Command walkCommand = new WalkCommand();
walkCommand.setReceiver(cat, dog);
invoker.setCommand(walkCommand);
invoker.action();

System.out.println("都坐下------------");
Command sitCommand = new SitCommand();
sitCommand.setReceiver(cat, dog);
invoker.setCommand(sitCommand);
invoker.action();

结果:

开始走————
猫在走…
狗在走…
都坐下————
猫坐下了…
狗坐下了…

可以看到,新建两个命令给调用者,调用者直接执行,客户端代码很简洁,可以看出命令模式的高内聚特点。另外,在具体情况中,命令中的 Receiver 并不都在抽象类中,很多都是由具体命令而定,这里放在抽象类中属于特殊情况。

总结


命令模式使得类之间的耦合度降低,这样就使得命令非常容易扩展,有新的命令直接实现抽象命令类就可以了,不需要更多的更改。

需要注意的是,命令模式最大的问题就是有多少个命令就需要有多少个具体命令类,因此,当命令特别多的时候,代码会变得相当臃肿。

猜你喜欢

转载自blog.csdn.net/rocketeerLi/article/details/81751311
今日推荐