1. 概述
命令模式(Command)将类的业务行为以对象的方式封装,以便实现行为的参数化、撤销或重做等需求。文章来源:https://www.toymoban.com/news/detail-729552.html
- 非命令模式的困惑:
类的行为在运行时是以实例方法的形式调用的,当方法执行完毕并返回后,方法栈将会消除;方法的运行状态(主要指局部变量)保存在栈帧中,它会随着方法栈的销毁而丢失。当方法的运行状态丢失时,撤销、重做等类似操作就很难顺利实现。- 命令模式的优势:
命令模式将目标类的业务行为分离出去,并用单独的对象类(称为命令类)封装。在程序运行时,被分离的业务行为作为一个独立的对象存在,可以被存储或参数化(作为参数在不同对象间传递),为实现该行为的撤销、重做等提供支持。
1.1 角色
- Command(抽象命令):一般定义为接口,用来定义执行的命令。
- ConcreteCommand(具体命令):通常会持有接收者对象,并调用接收者对象的相应功能来完成命令要执行的操作。
- Receiver(接收者):真正执行命令的对象。任何类都可能成为接收者,只要它能够实现命令要求实现的相应功能。
- Invoker(调用者):要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
- Client:创建具体的命令对象,并且设置命令对象的接收者。
1.2 类图
2. 代码示例
2.1 设计
- 定义一个抽象命令
Command
- 定义两个具体命令
Start
和Stop
- 它实现了抽象命令
Command
- 它继承了接收者
Service
- 它实现了抽象命令
- 定义一个接收者
Service
- 它有
Start()
和Stop()
两个方法分别对应它的启动和停止操作
- 它有
- 定义一个调用者
- 它是
Command
的聚合 - 它的AddCommand()方法将
Command
加入调用者 - 它的
Option()
方法执行了加入它的命令
- 它是
- 调用
- 实例化一个接收者
- 实例化两个具体命令
- 实例化一个执行者,各命令加入执行者
- 执行执行者的
Option()
方法 - 验证接收者状态
2.2 代码
- 代码
package main
import "fmt"
// 创建抽象命令
type Command interface {
execute()
}
// 创建具体命令start
type Start struct {
Status bool
Service *Service
}
func (s *Start) execute() {
err := s.Service.start()
if err != nil {
s.Status = true
}
s.Status = false
}
// 定义具体命令Stop
type Stop struct {
Status bool
Service *Service
}
func (s *Stop) execute() {
err := s.Service.stop()
if err != nil {
s.Status = true
}
s.Status = false
}
// 定义接收者
type Service struct {
status string
}
func (s *Service) start() (err error) {
fmt.Println("执行启动操作") //假装执行了操作,实际操作中如果有错这里会抛出
s.status = "Running"
return nil
}
func (s *Service) stop() (err error) {
fmt.Println("执行停止操作") //假装执行了停止,实际操作中如果有错这里会抛出
s.status = "Exited"
return nil
}
func (s *Service) GetStatus() {
fmt.Printf("服务状态:%+v", s.status)
}
// 调用者
type Invoker struct {
commands []Command
}
func (i *Invoker) AddCommand(command ...Command) {
i.commands = append(i.commands, command...)
}
func (i *Invoker) option() {
for _, command := range i.commands {
command.execute()
}
}
func main() {
//实例化一个接收者
myService := &Service{}
//实例化一个具体命令
start := &Start{
Service: myService,
}
//实例化另一个具体命令
stop := &Stop{
Service: myService,
}
//实例化一个调用者
invoker := &Invoker{}
//将刚才实例化的命令加入调用者
invoker.AddCommand(stop, start)
//执行操作
invoker.option()
//验证接受者状态
myService.GetStatus()
}
- 输出
执行停止操作
执行启动操作
服务状态:Running
2.3 类图
文章来源地址https://www.toymoban.com/news/detail-729552.html
到了这里,关于《golang设计模式》第三部分·行为型模式-02-命令模式(Command)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!