命令模式(Command Pattern),是行为型模式之一。在日常生活和开发过程中,这是一个非常常见的设计模式,比如我们电脑关机这个操作,我们只需要点击关机键便可以实现关机,内部是通过什么进行关机的,我们不需要去知道,计算机会帮我们实现这个功能。
优点:
(1)比较容易地实现一个命令队列。
(2)比较容易将队列记入日志。
(3)请求者和实现者通过接口进一步解耦。
(4)可以容易地实现对请求的撤销和恢复。
(5)加入新的命令不影响其它类的操作
引用上述关机的例子,对名词进行一些解释:
·Client(客户端):此处为我们自己,创建一个具体命令(ConcreteCommand)对象并确定其接收者。
·Invoker(请求者):关机键,负责调用命令对象执行请求,相关的方法叫做行动方法。
·Command(命令):声明了一个给所有具体命令类的抽象接口。
·ConcreteCommand(具体命令):调用关机的操作。
·Receicer(接收者):实现关机的操作。
接收者角色类
public class Receiver
{
/**
* 真正执行命令相应的操作
*/
public void action(){
System.out.println("执行操作");
}
}
抽象命令角色类
public interface Command
{
void execute();
}
具体命令角色类
public class ConcreteCommand implements Command
{
private Receiver receiver;
public ConcreteCommand(Receiver receiver)
{
this.receiver = receiver;
}
public void execute() {
// 调用并执行命令
receiver.action();
}
}
请求者角色类
public class Invoker
{
private Command command;
public Invoker(Command command)
{
this.command = command;
}
/**
* 行动方法,和Receive中的action()方法名称相同,却没有半毛钱关系
*/
public void action(){
command.execute();
}
}
客户端
public class Client
{
/**
* created by zm on 16-05-22
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建接收者
Receiver receiver = new Receiver();
//创建命令对象,设定它的接收者
Command command = new ConcreteCommand(receiver);
//创建请求者,把命令对象设置进去
Invoker invoker = new Invoker(command);
//执行方法
invoker.action();
}
}
现在我们在具体点讲一个事例,此处是开发过程中遇到的一个例子,在过去的开发中,曾经有一个界面,上面有着多处第三方登录,比如QQ登录,新浪微博登录,微信登录...
接收者角色类
public class Receiver
{
public void tencentLogin(){
System.out.println("QQ登录");
}
public void weChatLogin(){
System.out.println("weChat登录");
}
public void sinaLogin(){
System.out.println("sina登录");
}
}
抽象命令角色类
public interface Command
{
void execute();
}
具体命令角色类
public class SinaCommand implements Command
{
private Receiver receiver;
public SinaCommand(Receiver receiver)
{
this.receiver = receiver;
}
public void execute() {
receiver.sinaLogin();
}
}
public class TencentCommand implements Command
{
private Receiver receiver;
public TencentCommand(Receiver receiver)
{
this.receiver = receiver;
}
public void execute() {
receiver.tencentLogin();
}
}
public class WeChatCommand implements Command
{
private Receiver receiver;
public WeChatCommand(Receiver receiver)
{
this.receiver = receiver;
}
public void execute() {
receiver.weChatLogin();
}
}
请求者角色类
public class Invoker
{
//开发过程中没有此属性,此处作为示例,用来便利和撤销操作
private static List<Command> list = new ArrayList<Command>();
public Invoker(Command command)
{
list.add(command);
}
public void action(Command command){
command.execute();
}
public void removeAction(Command command){
if(list.contains(command)){
System.out.println(command.getClass().getName()+"被移除");
list.remove(command);
}
}
public void allAction(){
if(list.size()>0){
for (Command mCommand : list)
{
mCommand.execute();
}
}
}
}
客户端角色类
public class Client
{
/**
* created by zm on 16-05-22
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建接收者
Receiver receiver = new Receiver();
//创建命令对象,设定它的接收者
Command tencentCommand = new TencentCommand(receiver);
Command weChatCommand = new WeChatCommand(receiver);
Command sinaCommand = new SinaCommand(receiver);
//创建请求者,把命令对象设置进去
Invoker invoker = new Invoker(tencentCommand);
invoker = new Invoker(weChatCommand);
invoker = new Invoker(sinaCommand);
//执行方法
invoker.allAction();
System.out.println(".................");
invoker.removeAction(tencentCommand);
System.out.println(".................");
invoker.allAction();
}
}
执行后的结果如下:
QQ登录
weChat登录
sina登录
.................
com.zm.zero.TencentCommand被移除
.................
weChat登录
sina登录
总结:敏捷开发告诉我们,不要为了添加基于猜测的、实际不需要的功能,如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。
参考文献:《Java与模式》、《大话设计模式》《head first 设计模式》
微信扫我,_

网友评论