交互模式中的命令模式,在开始记录之前,要讲些自己的感受,真真切切的感受到了悟性的瓶颈!一共十页书,需要自己细细琢磨品味,至少三四遍才大概了解了他们间的逻辑,我需要调整下自己的学习思路,我之前是先看一遍(没看懂)然后去照着代码复现一遍,然后再看,效率低的不行,两个半小时十页书籍,悟性极差哇。
开始今天的小记:
先抓一下重点!找好它们之间的关联关系,通顺了之后,就可以小小的入门了。
目的为了实现发送请求者和接收者的解耦,实现一个有限的技能页面,技能页面只能同时放五个技能,而我当前后台可能有几十个技能。后端要则么知道我前端点的哪个技能呢?做一一对应嘛?在哪儿做,有没有更好的设计模式可以实现呢,带着这个问题开始今天的小记
命令模式的本质,是对请求进行封装,一个请求对应一个命令,将发出命令的责任和执行命令的责任划分开
命令模式的关键,在于引入了抽象命令类,请求发送这针对于抽象命令类进行编程,只有实现了抽象命令类的具体命令才与请求接收者相关联
在命令模式中,发送者与接收者之间引入了新的命令对象,将发送者的请求封装在命令对象中,再通过命令对象来调用接收者的方法
一个调用者,并不需要再设计时确定其接收者,因此他只与抽象命令类之间存在关联关系,在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的execute方法,
实现间接调用请求者的相关操作
上面这四句话,是我摘抄书上的原话,理解了很久,终于结合代码可以梳理明白了,下面我会写出类相关的关系。
例子 FBSettingWindow是“功能键设置”界面类, FunctionButton充当请求调用者, Command充当抽象命令类, MinimizeCommand和HelpCommand充当具体命令类, WindowHandler和HelpHandler充当请求接收者。
FBSettingWindow就相当于是我们的技能页面
FunctionButton 就是那一个个技能按钮
Command就是技能实现的抽象类
MinimizeCommand和HelpCommand就是链接技能效果的中间点
WindowHandler和HelpHandler充当请求接收者。
WindowHandler和HelpHandler就是技能的效果
完整代码如下:
<?xml version = "1.0"?> <config> <className>com.book.com.cor.command.test.HelpCommand</className> <className>com.book.com.cor.command.test.MinimizeCommand</className> </config>
关联关系图:
package com.book.com.cor.command.test;
/**
* @author liums
* @date 2024/7/28 16:10
* @description Client
*/
public class Client {
public static void main(String[] args) {
FBSettingWindows fb = new FBSettingWindows("功能键设置"); //
FunctionButton fb1,fb2;
fb1 = new FunctionButton("功能键1");
fb2 = new FunctionButton("功能键2");
Command command1,command2;
// 通过读取配置文件和反射生成具体命令对象
command1 =(Command) XMLUtil.getBean(0);
command2 =(Command) XMLUtil.getBean(1);
// 将命令对象注入功能键
fb.addFunctionButton(fb1);
fb.addFunctionButton(fb2);
fb.display();
// 调用功能键的业务方法
fb1.onClick();
fb2.onClick();
}
}
package com.book.com.cor.command.test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
/**
* @author liums
* @date 2024/7/28 15:57
* @description XMLUtil 该方法用于从xml文件中提取具体类类名,兵返回一个实例对象,可以通过参数的不同返回不同的实例
*/
public class XMLUtil {
public static Object getBean(int i) {
try {
// 创建文档对象
DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dfactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("src/main/resources/config.xml"));
// 获取包含类名的文本节点
NodeList nl = doc.getElementsByTagName("className");
Node classNode = null;
if (0 == i){
classNode = nl.item(0).getFirstChild();
}else {
classNode = nl.item(1).getFirstChild();
}
String cName = classNode.getNodeValue();
// 通过类名生成实例对象,并且将其返回
Class c = Class.forName(cName);
Object o = c.newInstance();
return o;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
package com.book.com.cor.command.test;
/**
* @author liums
* @date 2024/7/28 15:55
* @description WindowsHandler
*/
public class WindowsHandler {
public void minimize(){
System.out.println("将窗口最小化至托盘!");
}
}
package com.book.com.cor.command.test;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author liums
* @date 2024/7/28 15:54
* @description MinimizeCommand
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class MinimizeCommand extends Command{
private WindowsHandler whObj;
@Override
public void execute() {
whObj = new WindowsHandler();
}
}
package com.book.com.cor.command.test;
/**
* @author liums
* @date 2024/7/28 15:53
* @description HelpHandler
*/
public class HelpHandler {
public void display(){
System.out.println("显示帮助文档");
}
}
package com.book.com.cor.command.test;
/**
* @author liums
* @date 2024/7/26 22:24
* @description 抽象命令类,请求发送者针对抽象命令类编程,只有实现了抽象命令类的具体命令才能和请求接收者相关联
*/
abstract class Command {
public abstract void execute();
}
package com.book.com.cor.command.test;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.ArrayList;
/**
* @author liums
* @date 2024/7/28 15:44
* @description FBSettingWindows
*/
public class FBSettingWindows {
private String title;
// 储存所有功能键
private ArrayList<FunctionButton> functionButtons = new ArrayList<FunctionButton>();
public FBSettingWindows(String title) {
this.title = title;
}
public void addFunctionButton(FunctionButton button){
functionButtons.add(button);
}
public void removeButton(FunctionButton button){
functionButtons.remove(button);
}
public void display(){
System.out.println("窗口显示:"+this.title);
System.out.println("显示功能键");
for (FunctionButton functionButton : functionButtons) {
System.out.println(functionButton.getName());
}
System.out.println("-----------------------------------");
}
}
package com.book.com.cor.command.test;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.Setter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author liums
* @date 2024/7/28 15:38
* @description FunctionButton 请求发送者
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class FunctionButton {
private Command command;
private String name;
public void onClick(){
System.out.println("点击功能键:");
command.execute();
}
public FunctionButton(String name) {
this.name = name;
}
}
package com.book.com.cor.command.test;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author liums
* @date 2024/7/28 15:49
* @description HelpCommand 帮助命令类:具体命令类
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class HelpCommand extends Command{
private HelpHandler helpCommand;
@Override
public void execute() {
helpCommand.display();
}
}