网站打开不了怎样做,网站运营成本明细,本地服务器 wordpress,企业展馆展厅设计场景
欲开发一个桌面版应用程序#xff0c;该应用程序为用户提供了一系列自定义功能键#xff0c;用户可以通过这些功能键来实现一些快捷操作。
用户可以将功能键和相应功能绑定在一起#xff0c;还可以根据需要来修改功能键的设置#xff0c;而且系统在未来可能还会增加…场景
欲开发一个桌面版应用程序该应用程序为用户提供了一系列自定义功能键用户可以通过这些功能键来实现一些快捷操作。
用户可以将功能键和相应功能绑定在一起还可以根据需要来修改功能键的设置而且系统在未来可能还会增加一些新的功能或功能键。
如果不使用命令模式可能这样实现。
功能键类FunctionButton充当请求的发送者帮助文档处理类HelpHandler充当请求的接收者在发送者FunctionButton的onClick()
方法中将调用接收者HelpHandler的display()方法。
FunctionButton:
public class FunctionButton {//帮助文档处理类请求接收者private HelpHandler helperHandler;public void onClick(){helperHandler new HelpHandler();//显示帮助文档helperHandler.display();}
}
HelpHandler:
public class HelpHandler {public void display(){System.out.println(显示帮助文档);}
}
以上存在的问题
(1) 由于请求发送者和请求接收者之间存在方法的直接调用耦合度很高更换请求接收者必须修改发送者的源代码
如果需要将请求接收者HelpHandler改为WindowHanlder窗口处理类则需要修改FunctionButton的源代码违背了“开闭原则”。
(2) FunctionButton类在设计和实现时功能已被固定如果增加一个新的请求接收者如果不修改原有的FunctionButton类
则必须增加一个新的与FunctionButton功能类似的类这将导致系统中类的个数急剧增加。
由于请求接收者HelpHandler、WindowHanlder等类之间可能不存在任何关系它们没有共同的抽象层
因此也很难依据“依赖倒转原则”来设计FunctionButton。
(3) 用户无法按照自己的需要来设置某个功能键的功能一个功能键类的功能一旦固定在不修改源代码的情况下无法更换其功能
系统缺乏灵活性。
命令模式概述
在软件开发中我们经常需要向某些对象发送请求调用其中的某个或某些方法但是并不知道请求的接收者是谁
也不知道被请求的操作是哪个此时我们特别希望能够以一种松耦合的方式来设计软件使得请求发送者与请求接收者
能够消除彼此之间的耦合让对象之间的调用关系更加灵活可以灵活地指定请求接收者以及被请求的操作。
命令模式为此类问题提供了一个较为完美的解决方案。
命令模式可以将请求发送者和接收者完全解耦发送者与接收者之间没有直接引用关系发送请求的对象只需要知道如何发送请求
而不必知道如何完成请求。
命令模式(Command Pattern)
将一个请求封装为一个对象从而让我们可用不同的请求对客户进行参数化对请求排队或者记录请求日志以及支持可撤销的操作。
命令模式是一种对象行为型模式其别名为动作(Action)模式或事务(Transaction)模式。
命令模式结构图 命令模式包含的各角色
Command抽象命令类
抽象命令类一般是一个抽象类或接口在其中声明了用于执行请求的execute()等方法
通过这些方法可以调用请求接收者的相关操作。
ConcreteCommand具体命令类
具体命令类是抽象命令类的子类实现了在抽象命令类中声明的方法它对应具体的接收者对象
将接收者对象的动作绑定其中。在实现execute()方法时将调用接收者对象的相关操作(Action)。
Invoker调用者
调用者即请求发送者它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者
因此它只与抽象命令类之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中
再调用具体命令对象的execute()方法从而实现间接调用请求接收者的相关操作。
Receiver接收者
接收者执行与请求相关的操作它具体实现对请求的业务处理。命令模式的本质是对请求进行封装
一个请求对应于一个命令将发出命令的责任和执行命令的责任分割开。每一个命令都是一个操作
请求的一方发出请求要求执行一个操作接收的一方收到请求并执行相应的操作。
命令模式允许请求的一方和接收的一方独立开来使得请求的一方不必知道接收请求的一方的接口
更不必知道请求如何被接收、操作是否被执行、何时被执行以及是怎么被执行的。
注
博客霸道流氓气质_C#,架构之路,SpringBoot-CSDN博客
实现
使用命令模式实现以上用户自定义功能键。
1、新建抽象命令类
//抽象命令类
abstract class Command {public abstract void execute();
}
2、新建具体命令类:帮助命令类
//帮助命令类:具体命令类
public class HelpCommand extends Command{//维持对请求接收者的引用private HelpHandler helpHandler;public HelpCommand(){helpHandler new HelpHandler();}//命令执行方法将调用请求接收者的业务方法public void execute() {helpHandler.display();}
}
其中维持着对请求接收者的引用。
3、新建请求接收者帮助文档的处理类
//帮助文档处理类请求接受者
public class HelpHandler {public void display(){System.out.println(显示帮助文档);}
}
4、同理新建具体命令类:最小化命令类
//最小化命令类具体命令类
public class MinimizeCommand extends Command{//维持对请求接收者的引用private WindowHandler windowHandler;public MinimizeCommand(){windowHandler new WindowHandler();}//命令执行方法将调用请求接收者的业务方法public void execute() {windowHandler.minimize();}
}
其中维持着对请求接收者最小化窗口处理类的引用
5、新建最小化窗口处理类
//窗口处理类请求接收者
public class WindowHandler {public void minimize(){System.out.println(将窗口最小化);}
}
6、新建请求发送者功能键类
//功能键类请求发送者
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();}
}
7、新建功能键设置窗口类
import java.util.ArrayList;//功能键设置窗口类
public class FBSettingWindow {//窗口标题private String title;//定义一个ArrayList来存储所有功能键private ArrayListFunctionButton functionButtons new ArrayListFunctionButton();public FBSettingWindow(String title) {this.title title;}public String getTitle() {return title;}public void setTitle(String title) {this.title 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 (Object obj : functionButtons) {System.out.println(((FunctionButton)obj).getName());}System.out.println(-------------------------);}
}
8、客户端调用方式
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();}
}
9、总结
如果需要修改功能键的功能例如某个功能键可以实现“自动截屏”只需要对应增加一个新的具体命令类
在该命令类与屏幕处理者(ScreenHandler)之间创建一个关联关系然后将该具体命令类的对象通过配置文件注入到某个功能键即可
原有代码无须修改符合“开闭原则”。在此过程中每一个具体命令类对应一个请求的处理者接收者
通过向请求发送者注入不同的具体命令对象可以使得相同的发送者对应不同的接收者从而实现“将一个请求封装为一个对象
用不同的请求对客户进行参数化”客户端只需要将具体命令对象作为参数注入请求发送者无须直接操作请求的接收者。
命令模式的主要优点:
(1) 降低系统的耦合度。由于请求者与接收者之间不存在直接引用因此请求者与接收者之间实现完全解耦
相同的请求者可以对应不同的接收者同样相同的接收者也可以供不同的请求者使用两者之间具有良好的独立性。
(2) 新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响到其他类因此增加新的具体命令类很容易
无须修改原有系统源代码甚至客户类代码满足“开闭原则”的要求。
(3) 可以比较容易地设计一个命令队列或宏命令组合命令。
(4) 为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案。
命令模式的主要缺点如下
使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类
因此在某些系统中可能需要提供大量的具体命令类这将影响命令模式的使用。
适用场景
在以下情况下可以考虑使用命令模式
(1) 系统需要将请求调用者和请求接收者解耦使得调用者和接收者不直接交互。请求调用者无须知道接收者的存在也无须知道接收者是谁
接收者也无须关心何时被调用。
(2) 系统需要在不同的时间指定请求、将请求排队和执行请求。一个命令对象和请求的初始调用者可以有不同的生命期
换言之最初的请求发出者可能已经不在了而命令对象本身仍然是活动的可以通过该命令对象去调用请求接收者
而无须关心请求调用者的存在性可以通过请求日志文件等机制来具体实现。
(3) 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
(4) 系统需要将一组操作组合在一起形成宏命令。