标签:
这篇博客我们来介绍一下命令模式(Command Pattern),它是行为型设计模式之一。命令模式相对于其他的设计模式更为灵活多变,我们接触比较多的命令模式个例无非就是程序菜单命令,如在操作系统中,我们点击关机命令,系统就会执行一系列的操作,如先是暂停处理事件,保存系统的一些配置,然后结束程序进程,最后调用内核命令关闭计算机等,对于这一系列的命令,用户不用去管,用户只需点击系统的关机按钮即可完成如上一系列的命令。而我们的命令模式其实也与之相同,将一系列的方法调用封装,用户只需调用一个方法执行,那么所有的这些被封装的方法就会被挨个执行调用。
转载请注明出处:http://blog.csdn.net/self_study/article/details/52091539。
PS:对技术感兴趣的同鞋加群544645972一起交流。
将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
命令模式的使用场景:
我们来看看命令模式的 uml 类图:
命令模式的角色介绍:
public class Receiver {
public void action() {
System.out.print("执行具体的操作");
}
}
Command.class 抽象命令类
public interface Command {
void execute();
}
ConcreteCommand.clas 具体命令类
public class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}
Invoker.class 请求者
public class Invoker {
private Command command;
public Invoker(Command command) {
this.command = command;
}
public void action() {
command.execute();
}
}
Client 客户端
public class Client {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker(command);
invoker.action();
}
}
最后也能通过 Invoker 类调用到真正的 Receiver 执行逻辑了。
这就以一个简单的控制电灯亮灭和门开关的情景为例:
Light.class 和 Door.class 实际控制类
public class Light {
public void lightOn() {
System.out.print("light on\n");
}
public void lightOff() {
System.out.print("light off\n");
}
}
public class Door {
public void doorOpen() {
System.out.print("door open\n");
}
public void doorClose() {
System.out.print("door close\n");
}
}
然后是电灯的控制类:
LightOnCommand.class 和 LightOffCommand.class
public class LightOnCommand implements Command{
public Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.lightOn();
}
}
public class LightOffCommand implements Command{
public Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.lightOff();
}
}
门的相关控制类:
DoorOpenCommand.class 和 DoorCloseCommand.class
public class DoorOpenCommand implements Command{
public Door door;
public DoorOpenCommand(Door door) {
this.door = door;
}
@Override
public void execute() {
door.doorOpen();
}
}
public class DoorCloseCommand implements Command{
public Door door;
public DoorCloseCommand(Door door) {
this.door = door;
}
@Override
public void execute() {
door.doorClose();
}
}
然后是一个无操作默认命令类:
NoCommand.class
public class NoCommand implements Command{
@Override
public void execute() {
}
}
最后是控制类:
Controller.class
public class Controller {
private Command[] onCommands;
private Command[] offCommands;
public Controller() {
onCommands = new Command[2];
offCommands = new Command[2];
Command noCommand = new NoCommand();
onCommands[0] = noCommand;
onCommands[1] = noCommand;
offCommands[0] = noCommand;
offCommands[1] = noCommand;
}
public void setCommand(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onCommand(int slot) {
onCommands[slot].execute();
}
public void offCommand(int slot) {
offCommands[slot].execute();
}
}
测试代码
Light light = new Light();
Door door = new Door();
LightOnCommand lightOnCommand = new LightOnCommand(light);
LightOffCommand lightOffCommand = new LightOffCommand(light);
DoorOpenCommand doorOpenCommand = new DoorOpenCommand(door);
DoorCloseCommand doorCloseCommand = new DoorCloseCommand(door);
Controller controller = new Controller();
controller.setCommand(0, lightOnCommand, lightOffCommand);
controller.setCommand(1, doorOpenCommand, doorCloseCommand);
controller.onCommand(0);
controller.offCommand(0);
controller.onCommand(1);
controller.offCommand(1);
结果:
这样就实现了对 Light 和 Door 的控制了,其实这个例子只是实现了对命令模式的基本框架而已,命令模式的用处其实在于它的日志和回滚撤销功能,每次执行命令的时候都打印出相应的关键日志,或者每次执行后都将这个命令保存进列表中并且每个命令实现一个 undo 方法,以便可以进行回滚。另外,也可以构造一个 MacroCommand 宏命令类用来按次序先后执行几条相关联命令。当然可以发散的空间很多很多,感兴趣的可以自己去实现,原理都是一样的。
命令模式将发出请求的对象和执行请求的对象解耦,被解耦的两者之间通过命令对象进行沟通,调用者通过命令对象的 execute 放出请求,这会使得接收者的动作被调用,调用者可以接受命令当作参数,甚至在运行时动态地进行,命令可以支持撤销,做法是实现一个 undo 方法来回到 execute 被执行前的状态。MacroCommand 宏命令类是命令的一种简单的延伸,允许调用多个命令,宏方法也可以支持撤销。日志系统和事务系统可以用命令模式来实现。
命令模式的优点很明显,调用者和执行者之间的解耦,更灵活的控制性,以及更好的扩展性等。缺点更明显,就是类的爆炸,大量衍生类的创建,这也是大部分设计模式的“通病”,是一个没有办法避免的问题。
https://github.com/zhaozepeng/Design-Patterns/tree/master/CommandPattern
https://en.wikipedia.org/wiki/Command_pattern
http://blog.csdn.net/jason0539/article/details/45110355
java/android 设计模式学习笔记(16)---命令模式
标签:
原文地址:http://blog.csdn.net/self_study/article/details/52091539