其他分享
首页 > 其他分享> > 命令模式

命令模式

作者:互联网

命令模式

1 定义

命令模式(Command Pattern):将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式

2 命令模式结构图

在这里插入图片描述
Command(抽象命令类):抽象命令类一般是一个抽象类或接口,在其中声明了用于执行请求的execute()等方法,通过这些方法可以调用请求接收者的相关操作。
ConcreteCommand(具体命令类):具体命令类是抽象命令类的子类,实现了在抽象命令类中声明的方法,它对应具体的接收者对象,将接收者对象的动作绑定其中。在实现execute()方法时,将调用接收者对象的相关操作(Action)。
Invoker(调用者):调用者即请求发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的execute()方法,从而实现间接调用请求接收者的相关操作。
Receiver(接收者):接收者执行与请求相关的操作,它具体实现对请求的业务处理。

3 代码实现

abstract class Command {
	public abstract void execute();
}
class Invoker{
	private Command command;

	//构造注入
	public Invoker(Command command){
		this.command = command;
	}

	//设值注入
	public void setCommand(Command command){
		this.command = command;
	}

	// 业务方法,用于调用命令类的execute方法
	public void call(){
		command.execute();
	}
}
class ConcreteCommand extends Command{
	private Receiver receiver; //维持一个对请求接收者对象的引用

	public void execute(){
		receiver.action();//调用请求接收者的业务处理方法action()
	}
}
class Receiver{
	public void action(){
		......
	}
}

4 具体实例

开发一个桌面版应用程序,该程序为用户提供了一系列自定义功能键,用户可以通过这些功能键定义一些快捷键.不同的用户可能会有不同的使用习惯,在设置功能键的时候每个人都有自己的喜好,例如有的人喜欢将第一个功能键设置为“打开帮助文档”,有的人则喜欢将该功能键设置为“最小化至托盘”,为了让用户能够灵活地进行功能键的设置,提供了一个“功能键设置”窗口,窗口界面如下:
在这里插入图片描述
完整解决方案如下:
在这里插入图片描述
代码实现

public class FBSettingWindow {

    private String title;//窗口标题
    //定义一个ArrayList来存储所有功能键
    private ArrayList<FunctionButton> functionButtons = new ArrayList<FunctionButton>();
    public FBSettingWindow(String title){
        this.title = title;
    }
    public void setTitle(String title){
        this.title = title;
    }
    public String getTitle() {
        return title;
    }
    public void addFunctionButton(FunctionButton fb){
        functionButtons.add(fb);
    }
    public void removeFunctionButton(FunctionButton fb){
        functionButtons.remove(fb);
    }

    public void display(){
        System.out.println("显示窗口:" + this.title);
        System.out.println("显示功能键:");
        for (FunctionButton functionButton : functionButtons) {
            System.out.println(functionButton.getName());
        }
        System.out.println("------------------------");
    }
}
public class FunctionButton {

    private String name;//功能键名称
    private Command command;//维持一个抽象命令对象的引用

    public FunctionButton(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

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

    /**
     * 发送请求的方法
     */
    public void onClick(){
        System.out.println("点击功能键");
        command.execute();
    }

}
abstract public class Command {
    public abstract  void execute();
}
public class HelpCommand extends Command {

    private HelpHandler hhObj;//维持对请求接收者的引用

    public HelpCommand(){
        hhObj = new HelpHandler();
    }

    /**
     * 命令执行方法,将调用请求接收者的业务方法
     */
    @Override
    public void execute() {
        hhObj.display();
    }

}

/**
 * 帮助文档处理类:请求接收者
 */
public class HelpHandler {

    public void display(){
        System.out.println("显示帮助文档!");
    }

}
public class MinimizeCommand extends Command {

    private WindowHanlder whObj;//维持对请求接收者的引用

    public MinimizeCommand(){
        whObj = new WindowHanlder();
    }

    @Override
    public void execute() {
        whObj.minimize();
    }
}
public class WindowHanlder {
    public void minimize(){
        System.out.println("将窗口最小化至托盘!");
    }
}
public class Client {
    public static void main(String[] args) {
        FBSettingWindow fbsw = new FBSettingWindow("功能键设置");
        FunctionButton fb1,fb2;
        fb1 = new FunctionButton("功能键1");
        fb2 = new FunctionButton("功能键2");

        Command command1,command2;
        command1 = new HelpCommand();
        command2 = new MinimizeCommand();

        //将命令对象注入功能键
        fb1.setCommand(command1);
        fb2.setCommand(command2);

        fbsw.addFunctionButton(fb1);
        fbsw.addFunctionButton(fb2);
        fbsw.display();

        //调用功能键的业务方法
        fb1.onClick();
        fb2.onClick();

    }
}

5 优缺点及适用场景

主要优点:
1)降低系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现完全解耦,相同的请求者可以对应不同的接收者,同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。
2)新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码,甚至客户类代码,满足“开闭原则”的要求。
3)可以比较容易地设计一个命令队列或宏命令(组合命令)。
4)为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案。
主要缺点:
使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调
用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这
将影响命令模式的使用。
适用场景:
1)系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。请求调用者无须知道接收者的存在,也无须知道接收者是谁,接收者也无须关心何时被调用。
2)系统需要在不同的时间指定请求、将请求排队和执行请求。一个命令对象和请求的初始调用者可以有不同的生命期,换言之,最初的请求发出者可能已经不在了,而命令对象本身仍然是活动的,可以通过该命令对象去调用请求接收者,而无须关心请求调用者的存在性,可以通过请求日志文件等机制来具体实现。
3)系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
4)系统需要将一组操作组合在一起形成宏命令。

标签:请求,void,接收者,模式,功能键,命令,public
来源: https://blog.csdn.net/musi_m/article/details/104774117