命令模式
定义
将一个请求封装为一个对象,根据不同的请求对客户进行参数化。
结构
Command(命令抽象类):定义一组可以执行的操作接口。
ConcreteCommand(具体命令类):它持有Receiver的引用,针对不同的命令执行具体的操作方法。
Receiver(接受者):定义执行者统一的接口,它可以是接口,也可以是具体实现类。
Invoker(调用类):它持有Command的引用,执行具体命令类。
类图
调用者类:
public class Invoker {
private Command command;
public Invoker(Command command) {
this.command = command;
}
public void execute(){
command.execute();
}
}
Command:
public abstract class Command {
//执行
public abstract void execute();
//撤销
public abstract void undo();
}
具体命令类A:
public class ConcreteCommandA extends Command{
private Reciver reciver;
public ConcreteCommandA(Reciver reciver){
this.reciver = reciver;
}
//执行
@Override
public void execute(){
reciver.methodA();
}
//撤销
@Override
public void undo() {
reciver.undo();
}
}
具体命令类B:
public class ConcreteCommandB extends Command{
private Reciver reciver;
public ConcreteCommandB(Reciver reciver){
this.reciver = reciver;
}
//执行
@Override
public void execute(){
reciver.methodB();
}
//撤销
@Override
public void undo() {
reciver.undo();
}
}
接受者类:
public class Reciver {
public void methodA(){
System.out.println("执行A");
}
public void methodB(){
System.out.println("执行B");
}
public void undo(){
System.out.println("撤销");
}
}
测试类:
public static void main(String[] args) {
Invoker invokerA = new Invoker(new ConcreteCommandA(new Reciver()));
invokerA.execute();
Invoker invokerB = new Invoker(new ConcreteCommandB(new Reciver()));
invokerB.execute();
}
测试结果:
案例
我们以小米智能手机控制家电为例,智能手机作为调度器,它持有具体命令类的引用,电视、点灯作为具体接受者类。
智能手机:
/**
* 小米手机作为调度器
*/
public class MIPhone {
private Command command;
public MIPhone(Command command){
this.command = command;
}
public void execute(){
command.execute();
}
}
Command:
/**
* 抽象命令定义一组方法
*/
public abstract class Command {
public abstract void execute();
public abstract void undo();
}
电视机命令:
public class TVCommand extends Command{
private Receiver receiver;
public TVCommand(Receiver receiver){
this.receiver = receiver;
}
@Override
public void execute() {
receiver.on();
}
@Override
public void undo() {
receiver.off();
}
}
电灯命令:
public class LightCommand extends Command{
private Receiver receiver;
public LightCommand(Receiver receiver){
this.receiver = receiver;
}
@Override
public void execute() {
receiver.on();
}
@Override
public void undo() {
receiver.off();
}
}
抽象接受者:
/**
* 定义家具的开关方法
*/
public abstract class Receiver {
public abstract void on();
public abstract void off();
}
电视机接受者:
public class TVReciver extends Receiver{
@Override
public void on() {
System.out.println("电视机打开了。。。");
}
@Override
public void off() {
System.out.println("电视机关掉了。。。");
}
}
电灯接收者:
public class LightReciver extends Receiver{
@Override
public void on() {
System.out.println("灯打开了。。。");
}
@Override
public void off() {
System.out.println("灯关掉了。。。");
}
}
测试类:
public static void main(String[] args) {
MIPhone miPhone1 = new MIPhone(new TVCommand(new TVReciver()));
miPhone1.execute();
MIPhone miPhone2 = new MIPhone(new LightCommand(new LightReciver()));
miPhone2.execute();
}
测试结果:
优点
1.它将一条命令转换成一个对象,根据这个对象执行不同的操作。
2.可扩展,新增一个命令类很容易。
3.降低耦合度。
缺点
大量的具体命令类会增加系统的复杂度。
JDK类库中的命令模式
java.lang.Runnable
javax.swing.Action