命令模式是对象行为型使用率比较高的设计模式,别名:Action(动作),Transaction(事务)
[b]意图: 将一个请求封装为一个对象,从而使你可对不同的请求进行参数化;对请求排队或记录请求日志,以及支持可取消的操作 [/b]
这里所谓的“不同的请求”也既意味着请求可能发生的变化,是一个可能扩展的功能点。
动机: 方便扩展
结构:
[img]http://dl.iteye.com/upload/attachment/177849/5a29fa8f-fb37-3825-9399-fb12a5a85fb8.png[/img]
协作说明:
参与角色:
Command 声明一个接口以用来实现某个操作。
ConcreteCommand 将动作与Reciver对外绑定,通过调用Reciver对象的相应方法来实现Command的方法。
Client 创建ConcreteCommand对象,并设置其Reciver对象。
Invoker 要求该Command实现请求。
Reciver 知道如何实现具体的请求的类。
客户端创建了一个具体的Command对象并指定了其接收者。
调用者对象存储了此具体的Command对象。
调用者对象通过执行Command对象的Execute方法来实现当前请求。
如果命令是可以撤销时,具体对象在调用执行方法前将存储相应的状态以用来命令此请求。
具体的Command对象调用其接收者的方法从而来实现相应请求。
适用性:
[list]
[*]类似于 MenuItem , 抽象出待执行的动作以参数化某对象
[*]在不同的时刻指定,排列,执行请求
[*]支持撤消
[*]支持修改日志
[*]在构建在原语操作上的高层操作构造一个系统(其实就是事务)
[/list]
动态性方面: 像ruby中 block 就是命令模式
效果:
[list]
[*]命令模式将调用者对象与接收对象解耦(调用与实现解耦)。调用者实现功能时只需调用Command接口的Execute方法。
[*]具体的Commands对象是第一层对象,它们可以像其他对象一样被扩展或操作。
[*]你可以将多个Commands对象聚合成一个组合命令。组合命令也是组合对象模式的一个实例,将命令排队也是其的一种特殊情况。
[*]你可以很容易的添加新的命令,因为你并不需要修改现有的代码。这也符合了开闭原则,对修改关闭,对扩展开放。
[/list]
实现时应考虑命令对象应达到何种智能程序和支持撤消和重做这两个问题.
误用:
[list]
[*]不要着迷 到底哪个简单?
[*]命令模式不是说“做这个” 说“ 记住这个如何做”,稍后再说”按照我刚才要你记住的方法做这个”
[*]小心撤销,许多操作是破坏性的,如删除文件操作
[/list]
这里特别讲下观察者模式和命令模式的区别,
观察者模式没有顺序性,它的顺序不可把握,而命令模式是有顺序的,具备队列性质,并可撤销.
下面是个小例子,模拟短消息定服务:
类图:
[img]http://dl.iteye.com/upload/attachment/177857/6cec2e2c-73d7-35ea-822a-57557392b163.jpg[/img]
[b]意图: 将一个请求封装为一个对象,从而使你可对不同的请求进行参数化;对请求排队或记录请求日志,以及支持可取消的操作 [/b]
这里所谓的“不同的请求”也既意味着请求可能发生的变化,是一个可能扩展的功能点。
动机: 方便扩展
结构:
[img]http://dl.iteye.com/upload/attachment/177849/5a29fa8f-fb37-3825-9399-fb12a5a85fb8.png[/img]
协作说明:
参与角色:
Command 声明一个接口以用来实现某个操作。
ConcreteCommand 将动作与Reciver对外绑定,通过调用Reciver对象的相应方法来实现Command的方法。
Client 创建ConcreteCommand对象,并设置其Reciver对象。
Invoker 要求该Command实现请求。
Reciver 知道如何实现具体的请求的类。
客户端创建了一个具体的Command对象并指定了其接收者。
调用者对象存储了此具体的Command对象。
调用者对象通过执行Command对象的Execute方法来实现当前请求。
如果命令是可以撤销时,具体对象在调用执行方法前将存储相应的状态以用来命令此请求。
具体的Command对象调用其接收者的方法从而来实现相应请求。
适用性:
[list]
[*]类似于 MenuItem , 抽象出待执行的动作以参数化某对象
[*]在不同的时刻指定,排列,执行请求
[*]支持撤消
[*]支持修改日志
[*]在构建在原语操作上的高层操作构造一个系统(其实就是事务)
[/list]
动态性方面: 像ruby中 block 就是命令模式
效果:
[list]
[*]命令模式将调用者对象与接收对象解耦(调用与实现解耦)。调用者实现功能时只需调用Command接口的Execute方法。
[*]具体的Commands对象是第一层对象,它们可以像其他对象一样被扩展或操作。
[*]你可以将多个Commands对象聚合成一个组合命令。组合命令也是组合对象模式的一个实例,将命令排队也是其的一种特殊情况。
[*]你可以很容易的添加新的命令,因为你并不需要修改现有的代码。这也符合了开闭原则,对修改关闭,对扩展开放。
[/list]
实现时应考虑命令对象应达到何种智能程序和支持撤消和重做这两个问题.
误用:
[list]
[*]不要着迷 到底哪个简单?
[*]命令模式不是说“做这个” 说“ 记住这个如何做”,稍后再说”按照我刚才要你记住的方法做这个”
[*]小心撤销,许多操作是破坏性的,如删除文件操作
[/list]
这里特别讲下观察者模式和命令模式的区别,
观察者模式没有顺序性,它的顺序不可把握,而命令模式是有顺序的,具备队列性质,并可撤销.
下面是个小例子,模拟短消息定服务:
class SmsService
attr_accessor :service_list
def initialize
@service_list = []
end
def add_message(service)
@service_list << service
end
def do
@service_list.each do |sl|
sl.exec
end
end
end
class ServiceSystem
def do
puts '执行成功'
end
end
class Service
attr_accessor :service_system
def initialize(s)
@service_system = s
end
end
class ApplyShowNumberService < Service
def exec
puts '正在申请电显示服务'
service_system.do
end
end
class CancelShowNumberService < Service
def exec
puts '正在取消来电显示服务'
service_system.do
end
end
ss = SmsService.new
ss.add_message(ApplyShowNumberService.new(ServiceSystem.new))
ss.add_message(CancelShowNumberService.new(ServiceSystem.new))
ss.do
类图:
[img]http://dl.iteye.com/upload/attachment/177857/6cec2e2c-73d7-35ea-822a-57557392b163.jpg[/img]