博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【设计模式】—-(14)命令模式(行为型)
阅读量:4103 次
发布时间:2019-05-25

本文共 3961 字,大约阅读时间需要 13 分钟。

意图:将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或记录日志,以及支持可撤销的操作
动机:将”发出请求的对象”和”接收与执行这些请求的对象”分隔开来。
效果:
1)、command模式将调用操作的对象和实现该操作的对象解耦
2)、可以将多个命令装配成一个复合命令,复合命令是Composite模式的一个实例
3)、增加新的command很容易,无需改变已有的类
适用性:
1)、抽象出待执行的动作以参数化某对象
2)、在不同的时刻指定、排列和执行请求。如请求队列
3)、支持取消操作
4)、支持修改日志
5)、用构建在原语操作上的高层操作构造一个系统。支持事物
参与者:
1)、Command
  声明执行操作的接口
2)、ConcreteCommand
  将一个接收者对象绑定于一个动作
  调用接收者相应的操作,以实现execute
3)、Client
  创建一个具体命令对象并设定它的接收者
4)、Invoker
  要求该命令执行这个请求
5)、Receiver
  知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者
结构图:

协作:
1)、client创建一个ConcreteCommand对象并指定它的Receiver对象
2)、某Invoker对象存储该ConcreteCommand对象
3)、该Invoker通过调用Command对象的execute操作来提交一个请求。若该命令是可撤销的,ConcreteCommand在执行execute操作前存储当前状态以用于取消该命令
4)、ConcreteCommand对象调用它的Receiver的操作以执行该请求
命令对象将动作和接受者包进对象中,这个对象只暴露出一个execute()方法,当此方法被调用的时候,接收者就会进行这些动作。从外面来看,其他对象不知道究竟哪个接收者进行了哪些动作,只知道如果调用execute()方法,请求的目的就能达到。 

实例:

1 package com.test.patten.command; 2  3 /** 4  * 命令接口 5  */ 6 public interface Command { 7     /** 8      * 执行命令 9      */10     public void execute();11     /**12      * 撤销命令13      */14     public void undo();15 }
1 package com.test.patten.command; 2  3 /** 4  * 命令 5  */ 6 public class CreateCommand implements Command{ 7     private Receiver receiver; 8     private String state; 9     10     public CreateCommand(Receiver receiver){11         this.receiver = receiver;12     }13 14     @Override15     public void execute() {16         receiver.action();17     }18 19     @Override20     public void undo() {21         receiver.unAction();22     }23     24 }
1 package com.test.patten.command; 2  3 /** 4  * 命令接收者,命令真正执行人 5  */ 6 public class Receiver { 7     public void action(){ 8         System.out.println("执行命令..."); 9     }10     11     public void unAction(){12         System.out.println("撤销命令...");13     }14 }
1 package com.test.patten.command; 2  3 public class Invoker { 4     /** 5      * 调用者持有命令对象 6      */ 7     private Command command; 8  9     /**10      * 设置命令对象11      * @param command12      */13     public void setCommand(Command command) {14         this.command = command;15     }16     public Command getCommand() {17         return command;18     }19 20     /**21      * 执行命令22      */23     public void runCommand(){24         command.execute();25     }26     /**27      * 撤销命令28      */29     public void unDoCommand(){30         command.undo();31     }32 }
1 package com.test.patten.command; 2  3 public class Client { 4     public static void main(String[] args){ 5         //创建接受者 6         Receiver receiver = new Receiver(); 7         //创建命令对象,并设置它的接受者 8         Command command = new CreateCommand(receiver); 9         10         //创建调用者,将命令对象设置进去11         Invoker invoker = new Invoker();12         invoker.setCommand(command);13         14         //这里可以测试一下15         invoker.runCommand();16         invoker.unDoCommand();17     }18 }

常见应用:
1、工作队列,线程池,日程安排
2、日志请求(系统恢复)
要点:
1、命令模式将发出请求的对象和执行请求的对象解耦
2、在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组动作
3、调用者通过调用命令对象的execute()发出请求,这会使得接收者的动作被调用
4、调用者可以接受命令当作参数,甚至在运行时动态的进行
5、命令可以支持撤销,做法是实现一个undo()方法来回到execute()被执行前的状态
6、宏命令是命令的一种简单的延伸,允许调用多个命令。宏方法也可以支持撤销
7、实际操作时,很常见使用"聪明"命令对象,也就是直接实现了请求,而不是将工作委托给接受者(弊端?)
8、命令也可以用来实现日志和事物系统

命令模式属于对象的行为模式。命令模式又称为行动(Action)模式或交易(Transaction)模式。

  命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

命令模式的结构

  命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。

  每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。

  命令允许请求的一方和接收请求的一方能够独立演化,从而具有以下的优点:

  (1)命令模式使新的命令很容易地被加入到系统里。

  (2)允许接收请求的一方决定是否要否决请求。

  (3)能较容易地设计一个命令队列。

  (4)可以容易地实现对请求的撤销和恢复。

  (5)在需要的情况下,可以较容易地将命令记入日志。

 

命令模式的优点

  ●  更松散的耦合

  命令模式使得发起命令的对象——客户端,和具体实现命令的对象——接收者对象完全解耦,也就是说发起命令的对象完全不知道具体实现对象是谁,也不知道如何实现。

  ●  更动态的控制

  命令模式把请求封装起来,可以动态地对它进行参数化、队列化和日志化等操作,从而使得系统更灵活。

  ●  很自然的复合命令

  命令模式中的命令对象能够很容易地组合成复合命令,也就是宏命令,从而使系统操作更简单,功能更强大。

  ●  更好的扩展性

  由于发起命令的对象和具体的实现完全解耦,因此扩展新的命令就很容易,只需要实现新的命令对象,然后在装配的时候,把具体的实现对象设置到命令对象中,然后就可以使用这个命令对象,已有的实现完全不用变化。

转载地址:http://leusi.baihongyu.com/

你可能感兴趣的文章
Linux设备模型(总线、设备、驱动程序和类)之二:device
查看>>
Linux设备模型(总线、设备、驱动程序和类)之三:device_driver && 多厂家驱动自动识别
查看>>
Linux设备模型(总线、设备、驱动程序和类)之四:class_register
查看>>
Linux 设备驱动框架
查看>>
使用busybox
查看>>
platform_device与platform_driver
查看>>
android平台6410背光修改
查看>>
Uboot之一:BootLoader的概念
查看>>
6410平台500W摄像头调试过程 && 拍照偏绿和图片保存等BUG
查看>>
linux的触摸屏之一:原理及APK调试
查看>>
python 正则表达式
查看>>
ubuntu基本操作 - ssh的使用
查看>>
Linux脚本(shell)编程(一) 简单入门HelloWorld
查看>>
Linux脚本(shell)编程(二) 基本语法
查看>>
射频模块的作用
查看>>
手机射频
查看>>
android的system.img,userdata.img,ramdisk.img分析
查看>>
android root 权限分析
查看>>
android平台下lcd调试流程
查看>>
android系统开发 AP 和 BP 简要说明
查看>>