一:场景示例
电脑开机过程,大家都用过吧,
1.我们要摁下按钮吧,
2.接着主板“嘀”下检查各个硬件通过
3.启动操作系统
4.进入桌面
二:ok,我们就用这样的场景使用命令模式,且看代码实现,不过实现前还是先介绍下命令模式吧,哈哈
命令模式(Command):将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或者记录请求日子,以及撤销等操作。(尼玛这个定义太抽象的)
命令模式的 结构和说明:
/**
* 命令接口,声明执行操作
* Created by Administrator on 2016/4/22.
*/
public interface Command {
/**
* 执行命令对应的操作
*/
public void execute();
}
package com.dy.command;
/**
* 命令接受者,真正执行命令的对象
* Created by Administrator on 2016/4/22.
*/
public class Receiver {
public void action(){
System.out.println("正在执行命令模式...");
}
}
/**
* 命令实现
* 通常持有接受者,并调用接受者的功能来完成命令要执行的操作。
* Created by Administrator on 2016/4/22.
*/
public class CommandImpl implements Command {
private Receiver receiver;//持有相应的接受者对象
private String status;//命令对象可以有自己的状态
public CommandImpl(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
//通常调用接受者对象相应方法,由接受者真正执行命令
this.receiver.action();
}
}
/**
* 调用者
* 要求命令对象执行请求,通常持有命令对象,可以持有很多命令对象
* 这是客户端真正触发命令并要求命令执行相应操作的地方,相当于所有命令对象的入口
* Created by Administrator on 2016/4/22.
*/
public class Invoker {
private Command command;//持有命令对象
/*
*设置命令
*/
public void setCommand(Command command) {
this.command = command;
}
/**
* 要求命令执行请求
*/
public void run(){
command.execute();
}
}
/**
* 创建具体命令对象,并设置命令对象的接受者
* Created by Administrator on 2016/4/22.
*/
public class Client {
public void doCommand() {
Receiver receiver = new Receiver(); //创建接受者者
Command command = new CommandImpl(receiver);//创建命令对象
Invoker invoker = new Invoker(); //创建Invoker
invoker.setCommand(command); //设置命令对象
invoker.run();
}
}
class Test{
public static void main(String[] args) {
Client client = new Client();
client.doCommand();
}
}
执行结果:
正在执行命令模式...
Process finished with exit code 0
三:使用命令模式来实现电脑开机
public interface MainBoard {
/**
* 定义接受者功能
*/
public void open();
public void reset();
}
/**
* 命令接受者,真正执行命令的对象
* Created by Administrator on 2016/4/22.
*/
public class GigaMainBoard implements MainBoard {
@Override
public void open() {
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("电脑关机中...");
open();
System.out.println("====电脑重启完成===");
}
}
/**
* 命令接口,声明执行操作
* Created by Administrator on 2016/4/22.
*/
public interface Command {
/**
* 执行命令对应的操作
*/
public void execute();
}
/**
* 命令实现
* 通常持有接受者,并调用接受者的功能来完成命令要执行的操作。
* Created by Administrator on 2016/4/22.
*/
public class OpenCommand implements Command {
/**
* 持有真正的命令实现-接受者
*/
private MainBoard mainBoard;
public OpenCommand(MainBoard mainBoard) {
this.mainBoard = mainBoard;
}
@Override
public void execute() {
//对于命令对象根本不需要关心命令如何执行(这里指如何开机),转掉接受者方法
this.mainBoard.open();
}
}
我后期有补上了重启按钮,所以代码中不要大惊小怪哦,
/**
* 命令实现
* 通常持有接受者,并调用接受者的功能来完成命令要执行的操作。
* Created by Administrator on 2016/4/22.
*/
public class ResetCommand implements Command {
/**
* 持有真正的命令实现-接受者
*/
private MainBoard mainBoard;
public ResetCommand(MainBoard mainBoard) {
this.mainBoard = mainBoard;
}
@Override
public void execute() {
//对于命令对象根本不需要关心命令如何执行,转掉接受者方法
this.mainBoard.reset();
}
}
其实这里就是解耦的问题了,怎么办?
机箱啊,用机箱封装下不就行了吗,哈哈
接下来我们提供机箱,在机箱上装好按钮(开机按钮)
/**
* 机箱,本身有按钮,即持有命令对象
* 调用者
* 要求命令对象执行请求,通常持有命令对象,可以持有很多命令对象
* 这是客户端真正触发命令并要求命令执行相应操作的地方,相当于所有命令对象的入口
* Created by Administrator on 2016/4/22.
*/
public class Box {
/**
* 开机命令
*/
private Command openCommand;
private Command resetCommand;
public void setOpenCommand(Command openCommand) {
this.openCommand = openCommand;
}
public void setResetCommand(Command resetCommand) {
this.resetCommand = resetCommand;
}
/**
* 按下按钮触发方法
*/
public void openButtonPressed() {
this.openCommand.execute();
}
/**
* 按下按钮出发方法
*/
public void resetButtonPressed() {
this.resetCommand.execute();
}
}
把主机搬到你面前
/**
* 把机箱按钮连接线插到主板上
*/
MainBoard mainBoard = new GigaMainBoard();
OpenCommand openCommand = new OpenCommand(mainBoard);
ResetCommand resetCommand = new ResetCommand(mainBoard);
/**
* 给机箱安装开机按钮
*/
Box box = new Box();
box.setOpenCommand(openCommand);
box.setResetCommand(resetCommand);
/**
* 摁下开机按钮
*/
box.openButtonPressed();
/**
* 重启下试试
*/
box.resetButtonPressed();
摁下开机和重试按钮试试效果吧,哈哈
技嘉主板正在开机,请稍后...
接通电源...
设备检查...
启动系统...
系统启动完成,进入桌面...
====电脑开始重启===
电脑关机中...
技嘉主板正在开机,请稍后...
接通电源...
设备检查...
启动系统...
系统启动完成,进入桌面...
====电脑重启完成===
Process finished with exit code 0
实际开发过程中Client和Invoker可以融合在一起。
五:命令模式组装过程的调用顺序示意图
命令模式执行过程的调用顺序示意图