Java设计模式之行为型-命令模式(UML类图+案例分析)

目录

一、基础概念

二、UML类图

三、角色设计

四、案例分析

1、基本实现

2、点餐案例 

五、总结


一、基础概念

1、将一个请求封装为一个对象,使您可以用不同的请求对客户进行参数化。

2、对请求排队或记录请求日志,以及支持可撤销的操作。

3、将命令对象与执行命令的对象分离,实现调用者和接收者的解耦。

其中命令对象是关键,它包含了一个接收者和一个执行操作的方法。该命令对象绑定一个接收者对象,并通过调用接收者相应的操作来完成执行请求的功能。

二、UML类图

Java设计模式之行为型-命令模式(UML类图+案例分析)_第1张图片

三、角色设计

角色 描述
抽象命令类 定义命令的接口,声明执行的方法
具体命令角色 具体命令类,实现了命令接口,绑定接收者,并实现执行命令的操作
接收者类 知道如何实施与执行一个请求相关的操作
调用者类 接收命令请求并执行命令
客户端类 创建命令对象并设定它的接收者

四、案例分析

1、基本实现

主要包含以下几个部分:

1、Command抽象命令类:定义了命令的公共接口一般是一个execute()方法。

2、ConcreteCommand具体命令角色:实现了Command接口,是具体的命令类,包含对Receiver对象的引用。其execute()方法会调用Receiver的相应方法。

3、Receiver接收者类:命令对象Indirect调用的接收者对象。实现了具体的业务逻辑。

4、Invoker调用者类:请求的调用者。其持有Command对象的引用,并通过command.execute()间接调用Receiver。

5、Client客户端类:创建Command和Receiver对象,并创建Invoker传入Command对象,最后调用Invoker的invoke()方法触发执行。

这个实现让调用者Invoker和接收者Receiver解耦,Invoker只与Command接口发生依赖,不需要知道具体的命令与接收者。

抽象命令类:

public interface Command {
    /**
     * 执行方法
     */
    void execute();
}

 接收者类:

public class Receiver {
    /**
     * 真正执行命令相应的操作
     */
    public void action(){
        System.out.println("执行操作");
    }
}

具体命令角色类:

public class ConcreteCommand implements Command {

    //持有相应的接收者对象
    private Receiver receiver = null;
    /**
     * 构造方法
     */
    public ConcreteCommand(Receiver receiver){
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        //通常会转调接收者对象的相应方法,让接收者来真正执行功能
        receiver.action();
    }

}

调用者类:

public class Invoker {
    /**
     * 持有命令对象
     */
    private Command command = null;
    /**
     * 构造方法
     */
    public Invoker(Command command){
        this.command = command;
    }
    /**
     * 行动方法
     */
    public void action(){
        command.execute();
    }
}

客户端: 

public class Client {

    public static void main(String[] args) {
        //创建接收者
        Receiver receiver = new Receiver();
        //创建命令对象,设定它的接收者
        Command command = new ConcreteCommand(receiver);
        //创建请求者,把命令对象设置进去
        Invoker invoker = new Invoker(command);
        //执行方法
        invoker.action();
    }

}

运行结果如下:

Java设计模式之行为型-命令模式(UML类图+案例分析)_第2张图片

2、点餐案例 

这个点餐的命令模式案例,主要演示了几个角色对象之间的关系:

1、Waiter是接收者对象,知道如何执行点餐操作。

2、OrderCommand是命令对象,它封装了一个点餐请求,绑定了接收者Waiter。可以调用execute()执行点餐。

3、Customer是调用者对象,它通过命令对象indirect地执行点餐请求。可以设定并触发命令。

4、Client是客户端,进行对象的创建和使用。

抽象命令类:

public interface Command {

    public void execute();

}

服务员(接收者类):

public class Waiter {

    public void takeOrder(String food) {
        System.out.println("服务员:收到点餐,食物是:" + food);
    }

}

点餐命令类(具体的命令类):

public class OrderCommand implements Command {

    private Waiter waiter;
    private String food;

    public OrderCommand(Waiter waiter, String food) {
        this.waiter = waiter;
        this.food = food;
    }

    @Override
    public void execute() {
        waiter.takeOrder(food);
    }

}

顾客(调用者类):

public class Customer {

    private Command command;

    public void setOrder(Command command) {
        this.command = command;
    }

    public void orderUp() {
        command.execute();
    }

}

客户端类: 

public class Client {
    
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        Command cmd = new OrderCommand(waiter, "番茄炒蛋");

        Customer customer = new Customer();
        customer.setOrder(cmd);
        customer.orderUp();
    }
    
}

运行结果如下:

Java设计模式之行为型-命令模式(UML类图+案例分析)_第3张图片

整个执行流程是:

1、Client创建Waiter、OrderCommand、Customer对象。

2、Client把OrderCommand命令对象设置给Customer调用者。

3、Client请求Customer调用orderUp方法。

4、Customer的orderUp方法内部将调用OrderCommand的execute。

5、OrderCommand的execute会调用其内部绑定的Waiter的takeOrder方法。

6、这样客户的请求就通过命令对象传达给服务员,进行点餐。

这实现了调用者与接收者的解耦,并且使用命令对象可以方便实现撤销、重做、日志等功能。 

五、总结

优点:

1、解耦了命令的发出者和执行者:发出命令的对象只需要知道命令接口,不需要知道具体的命令执行者。

2、可以较容易地设计一个命令队列和宏命令:通过命令队列可以对命令进行排队,而宏命令可以执行一系列的命令。

3、可以较容易实现命令的撤销和重做:通过保存执行过的命令对象,可以方便地实现回退。

缺点:

1、可能产生很多具体的命令类:因为每一个命令都需要一个具体的命令类,所以如果命令种类很多,会导致类的个数增加很多。

2、系统可能要慢一点,因为每次执行命令时,都需要先创建命令对象。

应用场景:

1、需要对操作进行记录、撤销/重做、事务等处理的场景。命令模式可以方便实现这些功能。

2、需要将请求调用者和请求接收者解耦的场景。命令模式可以使两者独立变化。

3、需要把操作封装成对象传递和存储的场景。命令模式可以把操作转换为对象。

4、需要对操作进行排队或记录日志、支持事务等功能的场景。可以用命令队列实现排队,用命令对象记录日志。

5、需要支持向组合系统中添加新命令的场景。命令模式使新增命令比较方便。

6、需要对系统进行状态恢复的场景。可以利用命令对象实现状态恢复。

7、需要实现宏命令、也就是组合命令的场景。命令模式可以方便实现宏命令。 

符合的设计原则:

1、开闭原则(Open-Closed Principle)

命令模式中,命令的执行者与发出者是解耦的,发出者只知道命令接口,具体的实现执行者可以新增而不需要修改发出者。这样就满足了开闭原则。

2、单一职责原则(Single Responsibility Principle)

命令模式把请求的发出者和执行者进行了分离,发出者负责发出命令请求,执行者负责具体执行,职责划分明确,都满足单一职责原则。

3、组合复用原则(Composite Reuse Principle)

命令模式可以方便地将多个命令组合成一个组合命令,满足组合复用原则。

4、里氏替换原则(Liskov Substitution Principle)

命令模式中抽象命令类规定了接口,具体命令类都遵循这个接口,满足里氏替换原则。

你可能感兴趣的:(设计模式,Java,java,设计模式,命令模式,uml)