设计模式笔记 - 命令模式

168 阅读2分钟

命令模式是一种行为设计模式,它可将请求转换为一个包含与请求相关的所有信息的独立对象。该转换让你能根据不同的请求将方法参数化、延迟请求执行或将其放入队列中,且能实现可撤销操作。


解决什么问题?

  • 如果你需要通过操作来参数化对象,可使用命令模式。
  • 如果你想要将操作放入队列中、操作的执行或者远程执行操作,可使用命令模式。
  • 如果你想要实现操作回滚功能,可使用命令模式。

优势:

  • 单一职责原则。 你可以解耦触发和执行操作的类。
  • 开闭原则。 你可以在不修改已有客户端代码的情况下在程序中创建新的命令。
  • 你可以实现撤销和恢复功能。
  • 你可以实现操作的延迟执行。
  • 你可以将一组简单命令组合成一个复杂命令

劣势:

  • 代码可能会变得更加复杂,因为你在发送者和接收者之间增加了一个全新的层次。

实现步骤:

  • 定义命令接口
  • 具体命令类实现命令接口具体命令类关联接收者类
  • 定义接收者类,该类执行具体的操作
  • 定义发送者类,将该类与具体命令类关联,通过具体命令类调用接收者类的执行函数
  • 客户端关联具体命令类发送者类接收者类

下面是实现代码:

package main

import "fmt"

type command interface {
	execute()
}

type drawCmd struct {
	r      *receiver
	params int
}

func newDrawCmd(r *receiver, params int) *drawCmd {
	return &drawCmd{
		r:      r,
		params: params,
	}
}

func (d *drawCmd) execute() {
	d.r.operation(d.params)
}

type moveCmd struct {
	r      *receiver
	params int
}

func newMoveCmd(r *receiver, params int) *moveCmd {
	return &moveCmd{
		r:      r,
		params: params,
	}
}

func (m *moveCmd) execute() {
	m.r.operation(m.params)
}

type sender struct {
	c command
}

func newSender(c command) *sender {
	return &sender{c: c}
}

func (s *sender) setCmd(c command) {
	s.c = c
}

func (s *sender) executeCmd() {
	s.c.execute()
}

type receiver struct{}

func (r *receiver) operation(params int) {
	fmt.Println("do something with params:", params)
}

func main() {
	r := &receiver{}
	dc := newDrawCmd(r, 1)
	s := newSender(dc)
    s.executeCmd() // do something with params: 1

	mc := newMoveCmd(r, 2) // do something with params: 2
    s.setCmd(mc)
    s.executeCmd()
}

参考