当前位置:首页 > 编程笔记 > 正文
已解决

《golang设计模式》第三部分·行为型模式-02-命令模式(Command)

来自网友在路上 163863提问 提问时间:2023-10-31 12:17:29阅读次数: 63

最佳答案 问答题库638位专家为你答疑解惑

文章目录

  • 1. 概述
    • 1.1 角色
    • 1.2 类图
  • 2. 代码示例
    • 2.1 设计
    • 2.2 代码
    • 2.3 类图

1. 概述

命令模式(Command)将类的业务行为以对象的方式封装,以便实现行为的参数化、撤销或重做等需求。

  • 非命令模式的困惑:
    类的行为在运行时是以实例方法的形式调用的,当方法执行完毕并返回后,方法栈将会消除;方法的运行状态(主要指局部变量)保存在栈帧中,它会随着方法栈的销毁而丢失。当方法的运行状态丢失时,撤销、重做等类似操作就很难顺利实现。
  • 命令模式的优势:
    命令模式将目标类的业务行为分离出去,并用单独的对象类(称为命令类)封装。在程序运行时,被分离的业务行为作为一个独立的对象存在,可以被存储或参数化(作为参数在不同对象间传递),为实现该行为的撤销、重做等提供支持。

1.1 角色

  • Command(抽象命令):一般定义为接口,用来定义执行的命令。
  • ConcreteCommand(具体命令):通常会持有接收者对象,并调用接收者对象的相应功能来完成命令要执行的操作。
  • Receiver(接收者):真正执行命令的对象。任何类都可能成为接收者,只要它能够实现命令要求实现的相应功能。
  • Invoker(调用者):要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
  • Client:创建具体的命令对象,并且设置命令对象的接收者。

1.2 类图

<style>#mermaid-svg-tJkLdD8pCohya3Fd {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-tJkLdD8pCohya3Fd .error-icon{fill:#552222;}#mermaid-svg-tJkLdD8pCohya3Fd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tJkLdD8pCohya3Fd .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-tJkLdD8pCohya3Fd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tJkLdD8pCohya3Fd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tJkLdD8pCohya3Fd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tJkLdD8pCohya3Fd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tJkLdD8pCohya3Fd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tJkLdD8pCohya3Fd .marker.cross{stroke:#333333;}#mermaid-svg-tJkLdD8pCohya3Fd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tJkLdD8pCohya3Fd g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-tJkLdD8pCohya3Fd g.classGroup text .title{font-weight:bolder;}#mermaid-svg-tJkLdD8pCohya3Fd .nodeLabel,#mermaid-svg-tJkLdD8pCohya3Fd .edgeLabel{color:#131300;}#mermaid-svg-tJkLdD8pCohya3Fd .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-tJkLdD8pCohya3Fd .label text{fill:#131300;}#mermaid-svg-tJkLdD8pCohya3Fd .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-tJkLdD8pCohya3Fd .classTitle{font-weight:bolder;}#mermaid-svg-tJkLdD8pCohya3Fd .node rect,#mermaid-svg-tJkLdD8pCohya3Fd .node circle,#mermaid-svg-tJkLdD8pCohya3Fd .node ellipse,#mermaid-svg-tJkLdD8pCohya3Fd .node polygon,#mermaid-svg-tJkLdD8pCohya3Fd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tJkLdD8pCohya3Fd .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-tJkLdD8pCohya3Fd g.clickable{cursor:pointer;}#mermaid-svg-tJkLdD8pCohya3Fd g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-tJkLdD8pCohya3Fd g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-tJkLdD8pCohya3Fd .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-tJkLdD8pCohya3Fd .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-tJkLdD8pCohya3Fd .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-tJkLdD8pCohya3Fd .dashed-line{stroke-dasharray:3;}#mermaid-svg-tJkLdD8pCohya3Fd #compositionStart,#mermaid-svg-tJkLdD8pCohya3Fd .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-tJkLdD8pCohya3Fd #compositionEnd,#mermaid-svg-tJkLdD8pCohya3Fd .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-tJkLdD8pCohya3Fd #dependencyStart,#mermaid-svg-tJkLdD8pCohya3Fd .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-tJkLdD8pCohya3Fd #dependencyStart,#mermaid-svg-tJkLdD8pCohya3Fd .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-tJkLdD8pCohya3Fd #extensionStart,#mermaid-svg-tJkLdD8pCohya3Fd .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-tJkLdD8pCohya3Fd #extensionEnd,#mermaid-svg-tJkLdD8pCohya3Fd .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-tJkLdD8pCohya3Fd #aggregationStart,#mermaid-svg-tJkLdD8pCohya3Fd .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-tJkLdD8pCohya3Fd #aggregationEnd,#mermaid-svg-tJkLdD8pCohya3Fd .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-tJkLdD8pCohya3Fd .edgeTerminals{font-size:11px;}#mermaid-svg-tJkLdD8pCohya3Fd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style>
«interface»
Command
+execute()
ConcreteCommand
-state: State
-receiver:Receiver
+execute()
Receiver
+CommandAction()
Invoker
+store()
Client
+store()

2. 代码示例

2.1 设计

  • 定义一个抽象命令Command
  • 定义两个具体命令StartStop
    • 它实现了抽象命令Command
    • 它继承了接收者Service
  • 定义一个接收者Service
    • 它有Start()Stop()两个方法分别对应它的启动和停止操作
  • 定义一个调用者
    • 它是Command的聚合
    • 它的AddCommand()方法将Command加入调用者
    • 它的Option()方法执行了加入它的命令
  • 调用
    • 实例化一个接收者
    • 实例化两个具体命令
    • 实例化一个执行者,各命令加入执行者
    • 执行执行者的Option()方法
    • 验证接收者状态

2.2 代码

  • 代码
package mainimport "fmt"// 创建抽象命令
type Command interface {execute()
}// 创建具体命令start
type Start struct {Status  boolService *Service
}func (s *Start) execute() {err := s.Service.start()if err != nil {s.Status = true}s.Status = false
}// 定义具体命令Stop
type Stop struct {Status  boolService *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 类图

<style>#mermaid-svg-spmTxHLNOKTEiivv {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-spmTxHLNOKTEiivv .error-icon{fill:#552222;}#mermaid-svg-spmTxHLNOKTEiivv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-spmTxHLNOKTEiivv .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-spmTxHLNOKTEiivv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-spmTxHLNOKTEiivv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-spmTxHLNOKTEiivv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-spmTxHLNOKTEiivv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-spmTxHLNOKTEiivv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-spmTxHLNOKTEiivv .marker.cross{stroke:#333333;}#mermaid-svg-spmTxHLNOKTEiivv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-spmTxHLNOKTEiivv g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-spmTxHLNOKTEiivv g.classGroup text .title{font-weight:bolder;}#mermaid-svg-spmTxHLNOKTEiivv .nodeLabel,#mermaid-svg-spmTxHLNOKTEiivv .edgeLabel{color:#131300;}#mermaid-svg-spmTxHLNOKTEiivv .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-spmTxHLNOKTEiivv .label text{fill:#131300;}#mermaid-svg-spmTxHLNOKTEiivv .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-spmTxHLNOKTEiivv .classTitle{font-weight:bolder;}#mermaid-svg-spmTxHLNOKTEiivv .node rect,#mermaid-svg-spmTxHLNOKTEiivv .node circle,#mermaid-svg-spmTxHLNOKTEiivv .node ellipse,#mermaid-svg-spmTxHLNOKTEiivv .node polygon,#mermaid-svg-spmTxHLNOKTEiivv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-spmTxHLNOKTEiivv .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-spmTxHLNOKTEiivv g.clickable{cursor:pointer;}#mermaid-svg-spmTxHLNOKTEiivv g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-spmTxHLNOKTEiivv g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-spmTxHLNOKTEiivv .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-spmTxHLNOKTEiivv .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-spmTxHLNOKTEiivv .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-spmTxHLNOKTEiivv .dashed-line{stroke-dasharray:3;}#mermaid-svg-spmTxHLNOKTEiivv #compositionStart,#mermaid-svg-spmTxHLNOKTEiivv .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-spmTxHLNOKTEiivv #compositionEnd,#mermaid-svg-spmTxHLNOKTEiivv .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-spmTxHLNOKTEiivv #dependencyStart,#mermaid-svg-spmTxHLNOKTEiivv .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-spmTxHLNOKTEiivv #dependencyStart,#mermaid-svg-spmTxHLNOKTEiivv .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-spmTxHLNOKTEiivv #extensionStart,#mermaid-svg-spmTxHLNOKTEiivv .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-spmTxHLNOKTEiivv #extensionEnd,#mermaid-svg-spmTxHLNOKTEiivv .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-spmTxHLNOKTEiivv #aggregationStart,#mermaid-svg-spmTxHLNOKTEiivv .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-spmTxHLNOKTEiivv #aggregationEnd,#mermaid-svg-spmTxHLNOKTEiivv .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-spmTxHLNOKTEiivv .edgeTerminals{font-size:11px;}#mermaid-svg-spmTxHLNOKTEiivv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style>
Invoker
+commands:[]Command
+AddCommand(command ...Command)
option()
«interface»
Command
+execute()
Start
+Status:bool
+Service:*Service
+Execute()
Stop
+Status:bool
+Service:*Service
+Execute()
Service
+status:string
+start() error)
+stop()error)
+GetStatus()
查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"《golang设计模式》第三部分·行为型模式-02-命令模式(Command)":http://eshow365.cn/6-28620-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!