ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

命令模式

2020-03-15 20:05:03  阅读:206  来源: 互联网

标签:请求 void 接收者 模式 功能键 命令 public


命令模式

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有