大话设计模式—命令模式

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。主要解决在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

大话设计模式中程杰老师给出的定义是,命令模式:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作

通过调用者调用接受者执行命令来实现整个流程,顺序:调用者→接受者→命令;

关键要定义三个角色:

1、invoker 使用命令对象的入口
2、Command命令对象
3、received 真正的命令执行对象

大话设计模式—命令模式_第1张图片

package com.command;
/** * 用来声明执行操作的接口 * @author LMB * */
public abstract class Command {

    protected Receiver receiver;

    //当发布一个命令的时候需要知道该请求命令的接收者
    public Command(Receiver receiver){
        this.receiver = receiver;
    }

    public abstract void execute();

}
package com.command;

public class ConcreteCommand extends Command {

    public ConcreteCommand(Receiver receiver) {
        super(receiver);
    }

    @Override
    public void execute() {
        receiver.action();//让命令接收者去执行请求
    }

}
package com.command;
/** * 要求命令执行相应请求 * @author LMB * */
public class Invoker {

    private Command command;

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

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

}
package com.command;
/** * 知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者 * @author LMB * */
public class Receiver {

    public void action(){
        System.out.println("执行请求");
    }

}
package com.command;
/** * 创建一个具体命令对象并设定它的接收者 * @author LMB * */
public class CommandPatternDemo {

    Receiver receiver = new Receiver();
    Command command = new ConcreteCommand(receiver);

    Invoker invoker = new Invoker();    
    invoker.setCommand(command);
    invoker.executeCommand();

}

一个很适合的例子就是客人去饭馆吃饭,将要点的菜告诉服务员,服务员根据库存情况告知客人是否接受该预定,并将预定记录成订单,然后将订单告知后厨的师傅去具体执行做饭操作。如下类图所示:

大话设计模式—命令模式_第2张图片

命令模式的优点:

1、能比较容易的设计一个命令队列(客人的);
2、在需要的情况下,可以比较容易的将命令记入日志(服务员手中记录订单详情的本子);
3、允许接收请求的一方决定是否要否决请求(客人要点某个菜时,服务员可根据该菜是否有来决定接受或者拒绝客人的预定);
4、可以容易的实现对请求的撤销和重做;
5、由于加进新的具体命令类不影响其它的类,因此增加新的具体命令类很容易(增加菜系);
6、命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分隔开(客人不知道菜是怎么做出来的,只有厨师知道);

缺点:

使用命令模式可能会导致某些系统有过多的具体命令类。

使用场景:

认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。3、系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式。

应用实例:

struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的 Command。

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