案例分析:设计模式与代码的结构特性
Posted haorw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了案例分析:设计模式与代码的结构特性相关的知识,希望对你有一定的参考价值。
命令模式
命令模式(Command Pattern)将一个请求封装为一个对象,从而可以使用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销操作。命令模式又称为动作(Action)模式或者事务(Transaction)模式。
命令模式的适用性:
1)系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
2)系统需要在不同的时间指定请求、将请求排队和执行请求。
3)系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
4)系统需要将一组操作组合在一起,即支持宏命令。
1) 降低系统的耦合度:Command模式将调用操作的对象与知道如何实现该操作的对象解耦。
2) Command是头等的对象。它们可像其他的对象一样被操纵和扩展。
3) 组合命令:你可将多个命令装配成一个组合命令,即可以比较容易地设计一个命令队列和宏命令。一般说来,组合命令是Composite模式的一个实例。
4) 增加新的Command很容易,因为这无需改变已有的类。
5)可以方便地实现对请求的Undo和Redo。
命令模式的缺点:
使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。
命令模式的结构:
抽象命令类(Command):声明执行操作的接口。调用接收者相应的操作,以实现执行的方法Execute。
具体命令类(ConcreteCommand):创建一个具体命令对象并设定它的接收者。通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
调用者(Invoker):要求该命令执行这个请求。通常会持有命令对象,可以持有很多的命令对象。
接收者(Receiver):知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者,只要它能够实现命令要求实现的相应功能。
客户类(Client):创建具体的命令对象,并且设置命令对象的接收者。真正使用命令的客户端是从Invoker来触发执行。
案例:
家电遥控器就是一个典型的命令模式应用实例。
接收者(Receiver):门、电灯、电脑。
1 package com.zhy.pattern.command; 2 /** 3 * 门 4 * @author zhy 5 * 6 */ 7 public class Door 8 { 9 public void open() 10 { 11 System.out.println("打开门"); 12 } 13 14 public void close() 15 { 16 System.out.println("关闭门"); 17 } 18 }
1 package com.zhy.pattern.command; 2 3 /** 4 * 电灯 5 * @author zhy 6 * 7 */ 8 public class Light 9 { 10 public void on() 11 { 12 System.out.println("打开电灯"); 13 } 14 15 public void off() 16 { 17 System.out.println("关闭电灯"); 18 } 19 }
1 package com.zhy.pattern.command; 2 /** 3 * 电脑 4 * @author zhy 5 * 6 */ 7 public class Computer 8 { 9 public void on() 10 { 11 System.out.println("打开电脑"); 12 } 13 14 public void off() 15 { 16 System.out.println("关闭电脑"); 17 } 18 }
抽象命令类(Command):
1 package com.zhy.pattern.command; 2 3 public interface Command 4 { 5 public void execute(); 6 }
具体命令类(ConcreteCommand):
1 /** 2 * 关闭电灯的命令 3 * @author zhy 4 * 5 */ 6 public class LightOffCommond implements Command 7 { 8 private Light light ; 9 10 public LightOffCommond(Light light) 11 { 12 this.light = light; 13 } 14 15 @Override 16 public void execute() 17 { 18 light.off(); 19 } 20 } 21 22 /** 23 * 打开电灯的命令 24 * @author zhy 25 * 26 */ 27 public class LightOnCommond implements Command 28 { 29 private Light light ; 30 31 public LightOnCommond(Light light) 32 { 33 this.light = light; 34 } 35 36 @Override 37 public void execute() 38 { 39 light.on(); 40 } 41 } 42 43 package com.zhy.pattern.command; 44 45 /** 46 * 开电脑的命令 47 * @author zhy 48 * 49 */ 50 public class ComputerOnCommond implements Command 51 { 52 private Computer computer ; 53 54 public ComputerOnCommond( Computer computer) 55 { 56 this.computer = computer; 57 } 58 59 @Override 60 public void execute() 61 { 62 computer.on(); 63 } 64 } 65 66 package com.zhy.pattern.command; 67 68 /** 69 * 关电脑的命令 70 * @author zhy 71 * 72 */ 73 public class ComputerOffCommond implements Command 74 { 75 private Computer computer ; 76 77 public ComputerOffCommond( Computer computer) 78 { 79 this.computer = computer; 80 } 81 82 @Override 83 public void execute() 84 { 85 computer.off(); 86 } 87 }
调用者(Invoker):遥控器有9个按钮,提供了设置每个按钮的功能和点击的方法。
1 package com.zhy.pattern.command; 2 3 /** 4 * 控制器面板,一共有9个按钮 5 * 6 * @author zhy 7 * 8 */ 9 public class ControlPanel 10 { 11 private static final int CONTROL_SIZE = 9; 12 private Command[] commands; 13 14 public ControlPanel() 15 { 16 commands = new Command[CONTROL_SIZE]; 17 /** 18 * 初始化所有按钮指向空对象 19 */ 20 for (int i = 0; i < CONTROL_SIZE; i++) 21 { 22 commands[i] = new NoCommand(); 23 } 24 } 25 26 /** 27 * 设置每个按钮对应的命令 28 * @param index 29 * @param command 30 */ 31 public void setCommand(int index, Command command) 32 { 33 commands[index] = command; 34 } 35 36 /** 37 * 模拟点击按钮 38 * @param index 39 */ 40 public void keyPressed(int index) 41 { 42 commands[index].execute(); 43 } 44 }
使用了一个NoCommand对象,叫做空对象,这个对象的好处就是,我们不用执行前都判断个if(!=null),并且提供了一致的操作:
1 public class NoCommand implements Command 2 { 3 @Override 4 public void execute() 5 { 6 7 } 8 }
可以看到任意按钮可以随意配置任何命令,不用每次变一下需求就要改代码了,而是实现用户个性化;我们还可以配置到一个配置文件中实现完全的解耦。
多态机制:遥控器使用统一的命令接口,通过发出不同命令对不同的家电进行控制。
模块封装:遥控器封装成一个类,各电器封装成一个类,命令封装成一个类,客户封装成一个类。
耦合度:动作请求者与动作执行者完全解耦,上例中遥控器的按钮和电器之间不存在直接关系。
源代码:https://github.com/youlookwhat/DesignPattern
以上是关于案例分析:设计模式与代码的结构特性的主要内容,如果未能解决你的问题,请参考以下文章