目录
定义
几个参数
场景描述
代码示例
参数化设置
命令模式的优点
本质
何时选用
Command:定义命令的接口。
ConcreteCommand:命令接口的实现对象。但不是真正实现,是通过接收者的功能来完成命令要执行的操作
Receiver:接收者。真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能
Invoker:要求命令对象执行请求,通常持有命令对象。
Client:创建具体的命令对象,并且设置命令对象的接收者。
电脑开机:
机箱上的按钮就相当于是命令对象
机箱相当于是Invoker:要求机箱上的按钮执行哪些动作
主板相当于接收者对象:真正执行命令的对象
命令对象持有接收者对象就相当于按钮有一条线连接着主板,当按钮被按下就通过连接线把命令发出去。
定义主板
package day12命令模式;
/**
* 主板的接口
*/
public interface ZhuBanApi {
/**
* 定义一个功能:开机
*/
public void open();
}
定义实现,定义两个一个是技嘉主板,一个是微星主板,现在将实现写为一样
不同的主板对同一个命令的操作可以是不同的
技嘉主板
package day12命令模式.Impl;
import day12命令模式.ZhuBanApi;
public class JiJiaZhuBanImpl implements ZhuBanApi {
@Override
public void open() {
System.out.println("技嘉主板正在开机,请等候");
System.out.println("接通电源......");
System.out.println("设备检查......");
System.out.println("装载系统......");
System.out.println("机器正常运转......");
System.out.println("机器已经正常打开,请操作");
}
}
微星主板
package day12命令模式.Impl;
import day12命令模式.ZhuBanApi;
public class WeiXingZhuBanImpl implements ZhuBanApi {
@Override
public void open() {
System.out.println("微星主板正在开机,请等候");
System.out.println("接通电源......");
System.out.println("设备检查......");
System.out.println("装载系统......");
System.out.println("机器正常运转......");
System.out.println("机器已经正常打开,请操作");
}
}
定义命令接口:里面只有一个方法就是执行
package day12命令模式;
/**
* 命令接口,声明执行的操作
*/
public interface Command {
/**
* 执行命令对应的操作
*/
public void execute();
}
命令实现:我们按下的是按钮,但是按钮本身不知道怎么去启动电脑,只有主板知道,所以我们要持有真正实现命令的接收者--主板对象
package day12命令模式.Impl;
import day12命令模式.Command;
import day12命令模式.ZhuBanApi;
/**
* 开机命令接口的实现
*/
public class CommandImpl implements Command {
/**
* 持有真正实现命令的接收者--主板对象
*/
private ZhuBanApi zhuBanApi = null;
/**
* 构造方法,传入主板对象
* @param zhuBanApi
*/
public CommandImpl(ZhuBanApi zhuBanApi){
this.zhuBanApi = zhuBanApi;
}
/**
* 实现开机
*/
@Override
public void execute() {
this.zhuBanApi.open();
}
}
提供机箱,按钮是放置在机箱上的。机箱对象,本身有按钮,持有按钮对应的命令对象也就是Command
package day12命令模式;
/**
* 机箱对象,本身有按钮,持有按钮对应的命令对象
*/
public class Box {
/**
* 开机命令对象
*/
private Command openCommand;
/**
* 设置开机命令对象
* @param openCommand 开机命令对象
*/
public void setOpenCommand(Command openCommand) {
this.openCommand = openCommand;
}
/**
* 提供给客户使用,接收并相应用户请求,相当于那妞被按下触发的方法
*/
public void openButton(){
openCommand.execute();
}
}
客户使用按钮,把与主板连接好的按钮对象放置在机箱上。
package day12命令模式;
import day12命令模式.Impl.CommandImpl;
import day12命令模式.Impl.WeiXingZhuBanImpl;
public class Client {
public static void main(String[] args) {
// 1.创建接收者
WeiXingZhuBanImpl zhuban = new WeiXingZhuBanImpl();
// 2.设置接收者与命令对象的关系 (按钮要进行开机,使用哪个主板)
CommandImpl command = new CommandImpl(zhuban);
// 3.创建Invoker,用Invoker来执行命令
Box box = new Box();
// 4.将2中绑定好关系的命令对象设置到Invoker中,让Invoker持有
box.setOpenCommand(command);
// 5.调用Invoker中的方法,触发要求执行命令
// Box定义了方法,,用持有命令对象接口里面的方法,接口的实现中持有真正实现命令的接收者ZhuBanApi,
// ZhuBanApi他去调用真正的开机方法,而这个接口有多个实现类,到底调用哪一个呢?
// 因为在创建接收者时已经把微星这个接收者与命令对象绑定起来了,所以用的就是微星的实现类
box.openButton();
}
}
解析:先new一个主板,主板要跟按钮连接成为一个具体的开机命令,我又new一个机箱,把这个升级过的按钮(带有功能)装到这个机箱上,机箱最后调用这个按钮。
1.会发现命令模式的关键之处就是把请求封装成了对象,也就是命令对象,并定义了统一的执行操作的接口。
2.在命令模式中会有一个组装者,他来维护虚实现与真实实现之间的关系
可以用不同的命令对象,去参数化配置客户的请求
定义主板接口,现在增加一个重启的按钮,因此主板加一个方法来实现重启功能
package day12命令模式;
/**
* 主板的接口
*/
public interface ZhuBanApi {
/**
* 定义一个功能:开机
*/
public void open();
/**
* 定义重启功能
*/
public void reset();
}
实现类也要改一下
技嘉的
package day12命令模式.Impl;
import day12命令模式.ZhuBanApi;
/**
* 主板的实现
*/
public class JiJiaZhuBanImpl implements ZhuBanApi {
@Override
public void open() {
System.out.println("技嘉主板正在开机,请等候");
System.out.println("接通电源......");
System.out.println("设备检查......");
System.out.println("装载系统......");
System.out.println("机器正常运转......");
System.out.println("机器已经正常打开,请操作");
}
@Override
public void reset() {
System.out.println("技嘉主板现在正在重新启动机器,请等候");
System.out.println("机器已经正常打开,请操作");
}
}
微星的
package day12命令模式.Impl;
import day12命令模式.ZhuBanApi;
/**
* 主板的实现
*/
public class WeiXingZhuBanImpl implements ZhuBanApi {
@Override
public void open() {
System.out.println("微星主板正在开机,请等候");
System.out.println("接通电源......");
System.out.println("设备检查......");
System.out.println("装载系统......");
System.out.println("机器正常运转......");
System.out.println("机器已经正常打开,请操作");
}
@Override
public void reset() {
System.out.println("微星主板现在正在重新启动机器,请等候");
System.out.println("机器已经正常打开,请操作");
}
}
接下来定义命令和按钮,接口不变,添加一个重启命令的实现resetCommandImpl
package day12命令模式.Impl;
import day12命令模式.Command;
import day12命令模式.ZhuBanApi;
public class ResetCommandImpl implements Command {
/**
* 持有主板,也就是接收者对象
*/
private ZhuBanApi zhuBanApi;
/**
* 构造函数传入
* @param zhuBanApi
*/
public ResetCommandImpl(ZhuBanApi zhuBanApi){
this.zhuBanApi = zhuBanApi;
}
@Override
public void execute() {
this.zhuBanApi.reset();
}
}
Box改造一下,这里增加一个重启命令对象
package day12命令模式;
/**
* 机箱对象,本身有按钮,持有按钮对应的命令对象
*/
public class Box {
/**
* 开机命令对象
*/
private Command openCommand;
/**
* 重启命令对象
*/
private Command resetCommand;
public void setResetCommand(Command resetCommand) {
this.resetCommand = resetCommand;
}
/**
* 设置开机命令对象
* @param openCommand 开机命令对象
*/
public void setOpenCommand(Command openCommand) {
this.openCommand = openCommand;
}
/**
* 提供给客户使用,接收并相应用户请求,相当于按钮被按下触发的方法
*/
public void openButton(){
openCommand.execute();
}
/**
* 重启按钮
*/
public void resetButton(){
resetCommand.execute();
}
}
Client
package day12命令模式;
import day12命令模式.Impl.OpenCommandImpl;
import day12命令模式.Impl.ResetCommandImpl;
import day12命令模式.Impl.WeiXingZhuBanImpl;
public class Client {
public static void main(String[] args) {
WeiXingZhuBanImpl zhuban = new WeiXingZhuBanImpl();
OpenCommandImpl openCommand = new OpenCommandImpl(zhuban);
ResetCommandImpl resetCommand = new ResetCommandImpl(zhuban);
Box box = new Box();
box.setOpenCommand(openCommand);
box.setResetCommand(resetCommand);
System.out.println("正确配置");
System.out.println(">>>按下开机按钮:>>>");
box.openButton();
System.out.println(">>>按下重启按钮:>>>");
box.resetButton();
}
}
命令模式的本质:封装请求