在shell编程中经常会使用到Linux提供的命令,比如ls、cat、grep等等。这些命令给我们开发提供了很多便利。在设计模式中我们也可以将一个函数方法抽象成一个命令对象供外界直接调用,这样的组织形式很大程度的解耦了函数之间的调用关系,使得结构衔接变得松散。另一方面,这种调用可以将函数执行以队列的形式进行处理,让上下调用链关系更加容易控制。
总结一下,命令模式是把请求封装成命令对象,把发出命令的责任和执行命令的责任分割开。好处是可以将命令的发送者和执行者解耦;可以进行命令队列的实现;方便记录执行过程,方便扩展
定义
调度器(Invoker)
首先需要有一个调度器用来加入command和运行command。所以成员变量有一个command的数组,另外需要cmd能够直接运行,还需要cmd类型具有一个Exec()方法
// 定义Invoker
// 创建调度器
type Invoker struct {
cmds []ICommand
}
// 定义Command类型
type ICommand interface {
Exec() error // cmd应该具有exec方法
}
给Invoker增加两个方法:加入command和运行command
type IEquipInvoker interface {
AddCommand() // 调度器应该具有将命令加入执行队列的能力
Run() // 调度器可以执行内部的cmd
}
func (e *EquipInvoker) AddCommand(cmds ...ICommand) {
e.cmds = append(e.cmds, cmds...)
}
func (e *EquipInvoker) Run() {
for _, cmd := range e.cmds {
if err := cmd.Exec(); err != nil {
log.Logger.Errorf("%s", err.Error())
break
}
}
}
这样调度器就创建好了
封装command
我们的目的是将一个普通的func封装成一个ICommand类型的command。
假设现有函数为:
type InnerEquip struct {
ctx *context.Context
platform int
}
func NewInnerEquip(ctx *context.Context, platform int) *InnerEquip {
return &InnerEquip{ctx: ctx, platform: platform}
}
func (e *InnerEquip) ExtractKeyWords() map[string]model.EquipIntro {
// 业务逻辑...
return result
}
将ExtractKeyWords封装为cmd
type InnerEquipCommand struct {
*InnerEquip
}
func (e *InnerEquip) NewExtractKeyWordsCmd() *InnerEquipCommand {
return &InnerEquipCommand{
e,
}
}
// 补充Exec方法
func (cmd InnerEquipCommand) Exec() error {
cmd.ExtractKeyWords()
return nil
}
调用
invoker := new(equipment.EquipInvoker)
equipForLOLCmd := equipment.NewInnerEquip(ctx, common.PlatformForLOL).NewExtractKeyWordsCmd()
equipForLOLMCmd := equipment.NewInnerEquip(ctx, common.PlatformForLOLM).NewExtractKeyWordsCmd()
invoker.AddCommand(equipForLOLCmd, equipForLOLMCmd)
invoker.NonBlockRun()
评论区