Golang学习笔记_44——命令模式

news2025/3/10 18:15:59

Golang学习笔记_41——观察者模式
Golang学习笔记_42——迭代器模式
Golang学习笔记_43——责任链模式


文章目录

    • 一、核心概念
      • 1. 定义
      • 2. 解决的问题
      • 3. 核心角色
      • 4. 类图
    • 二、特点分析
    • 三、适用场景
      • 1. 事务管理系统
      • 2. 多媒体遥控器
      • 3. 操作审计系统
    • 四、Go语言实现示例
    • 五、高级应用
      • 1. 宏命令系统
      • 2. 异步命令队列
    • 六、与其他模式对比
    • 七、实现建议
    • 八、典型应用


一、核心概念

1. 定义

命令模式是一种行为型设计模式,通过将请求封装为独立对象实现调用者与执行者的解耦,支持请求的队列化、撤销重做和事务管理。其核心特点包括:
请求对象化:将操作抽象为可传递的命令对象
解耦调用链:调用者无需了解具体执行细节
操作可编排:支持命令的组合与顺序控制

2. 解决的问题

系统紧耦合:消除行为请求者与实现者的直接依赖
操作不可逆:缺乏标准化的撤销/重做机制
事务原子性:多步骤操作无法保证整体执行

3. 核心角色

角色作用
Command定义执行操作的统一接口(Execute/Undo)
ConcreteCommand实现具体命令逻辑,绑定接收者对象
Invoker触发命令执行,支持命令存储与调度
Receiver实际执行业务操作的对象
Client组装命令对象与接收者的关系

4. 类图

命令模式类图

@startuml
' 命令模式类图

interface Command {
    +execute(): void
}

class Invoker {
    -command: Command
    +setCommand(command: Command): void
    +executeCommand(): void
}

class ConcreteCommand {
    -receiver: Receiver
    +execute(): void
}

class Receiver {
    +action(): void
}

' 关系定义
Command <|.. ConcreteCommand
Invoker o--> Command
ConcreteCommand --> Receiver
Receiver <.. ConcreteCommand : <<create>>

note left of Command
  定义执行操作的接口
end note

note right of Receiver
  实际执行操作的对象
end note
@enduml

二、特点分析

优点

  1. 解耦架构:彻底分离请求发起方与执行方
  2. 可扩展性:新增命令不影响现有系统
  3. 事务支持:支持多命令原子操作与回滚

缺点

  1. 类膨胀:每个命令需独立类实现
  2. 执行开销:间接调用带来性能损耗
  3. 复杂度:需处理命令生命周期管理

三、适用场景

1. 事务管理系统

// 转账命令示例
type TransferCommand struct {
    from   *Account
    to     *Account
    amount int
}

func (t *TransferCommand) Execute() {
    t.from.Debit(t.amount)
    t.to.Credit(t.amount)
}

func (t *TransferCommand) Undo() {
    t.from.Credit(t.amount)
    t.to.Debit(t.amount)
}

(实现资金划转与回滚,参考的撤销实现)

2. 多媒体遥控器

type TVPowerCommand struct {
    tv *Television
}

func (c *TVPowerCommand) Execute() {
    if c.tv.IsOn {
        c.tv.TurnOff()
    } else {
        c.tv.TurnOn()
    }
}

3. 操作审计系统

type AuditLog struct {
    commands []Command
}

func (a *AuditLog) Record(cmd Command) {
    a.commands = append(a.commands, cmd)
    cmd.Execute()
}

四、Go语言实现示例

示例类图

完整实现代码

package command_demo

import "fmt"

// Command 接口
type Command interface {
	Execute()
}

// Receiver 实现
type StockTrade struct{}

func (s *StockTrade) Buy() {
	fmt.Println("买入股票")
}

func (s *StockTrade) Sell() {
	fmt.Println("卖出股票")
}

// ConcreteCommand 具体命令
type BuyStock struct {
	stock *StockTrade
}

func (b *BuyStock) Execute() {
	b.stock.Buy()
}

type SellStock struct {
	stock *StockTrade
}

func (s *SellStock) Execute() {
	s.stock.Sell()
}

// Invoker 调用者
type Broker struct {
	orders []Command
}

func (b *Broker) TakeOrder(cmd Command) {
	b.orders = append(b.orders, cmd)
}

func (b *Broker) PlaceOrders() {
	for _, cmd := range b.orders {
		cmd.Execute()
	}
	b.orders = nil
}

// 客户端代码
func Example() {
	stock := &StockTrade{}
	buy := &BuyStock{stock: stock}
	sell := &SellStock{stock: stock}

	broker := &Broker{}
	broker.TakeOrder(buy)
	broker.TakeOrder(sell)

	broker.PlaceOrders()
}

执行结果

=== RUN   TestExample
买入股票
卖出股票
--- PASS: TestExample (0.00s)
PASS

五、高级应用

1. 宏命令系统

type MacroCommand struct {
	commands []Command
}

func (m *MacroCommand) Execute() {
	for _, cmd := range m.commands {
		cmd.Execute()
	}
}

// 使用示例
macro := &MacroCommand{
	commands: []Command{
		&SaveCommand{},
		&CompileCommand{},
		&DeployCommand{},
	},
}
macro.Execute()

2. 异步命令队列

type AsyncInvoker struct {
	queue chan Command
}

func (a *AsyncInvoker) Start() {
	go func() {
		for cmd := range a.queue {
			cmd.Execute()
		}
	}()
}

func (a *AsyncInvoker) Add(cmd Command) {
	a.queue <- cmd
}

六、与其他模式对比

模式核心区别典型应用场景
策略模式算法选择 vs 操作封装支付方式选择
职责链模式请求传递 vs 命令执行审批流程处理
备忘录模式状态存储 vs 操作记录编辑器撤销功能

七、实现建议

  1. 轻量化设计:使用闭包简化简单命令
    func NewLightCmd(light *Light) Command {
        return CommandFunc(light.Toggle)
    }
    
  2. 生命周期管理:实现Release()方法释放资源
  3. 批量操作:采用组合模式实现命令集合操作
  4. 错误处理:增加Validate()预处理方法

八、典型应用

  1. 文本编辑器:实现编辑操作撤销栈
  2. 智能家居:物联网设备控制中心
  3. 金融交易:多步骤交易事务管理
  4. 游戏开发:玩家操作回放系统

通过命令模式,可以将分布式系统的操作请求转化为可序列化对象,实现跨网络的操作重放与审计。在Go语言中,结合channel特性可构建高性能命令管道,适用于实时交易系统等场景。建议对高频操作命令采用对象池优化,避免重复创建开销。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2312824.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【单片机通信技术】STM32 HAL库 SPI主从机通过串口发送数据

一、说明 使用STM32F103C8T6最小系统板&#xff0c;让板载SPI1与SPI2通信&#xff0c;通过串口收发数据。本文章说明了在配置与编写时遇到的一些问题&#xff0c;以及详细说明如何使用cubeMAX进行代码编写。 二、CubeMAX配置 1.时钟配置选择外部高速时钟 2.系统模式与时钟配…

laravel中 添加公共/通用 方法/函数

一&#xff0c;现在app 下面创建Common目录&#xff0c;然后在创建Common.php 文件 二&#xff0c;修改composer.json文件 添加这个到autoload 中 "files": ["app/Common/Common.php"]"autoload": {"psr-4": {"App\\": &quo…

Jetpack Compose — 入门实践

一、项目中使用 Jetpack Compose 从此节开始,为方便起见,如无特殊说明,Compose 均指代 Jetpack Compose。 开发工具: Android Studio 1.1 创建支持 Compose 新应用 新版 Android Studio 默认创建新项目即为 Compose 项目。 注意:在 Language 下拉菜单中,Kotlin 是唯一可…

P8686 [蓝桥杯 2019 省 A] 修改数组--并查集 or Set--lower_bound()的解法!!!

P8686 [蓝桥杯 2019 省 A] 修改数组--并查集 题目 并查集解析代码【并查集解】 Set 解法解析lower_bound代码 题目 并查集解析 首先先让所有的f&#xff08;i&#xff09;i&#xff0c;即每个人最开始的祖先都是自己&#xff0c;然后就每一次都让轮到那个数的父亲1&#xff08…

应用案例 | 精准控制,高效运行—宏集智能控制系统助力SCARA机器人极致性能

概述 随着工业4.0的深入推进&#xff0c;制造业对自动化和智能化的需求日益增长。传统生产线面临空间不足、效率低下、灵活性差等问题&#xff0c;尤其在现有工厂改造项目中&#xff0c;如何在有限空间内实现高效自动化成为一大挑战。 此次项目的客户需要在现有工厂基础上进行…

Greenplum6.19集群搭建

一&#xff0c;安装说明 1.1环境说明 1、首先确定部署的环境&#xff0c;确定下服务器的端口&#xff0c;一般默认是22的端口&#xff1b; 2、当前这份文档是服务器处于10022端口下部署的&#xff08;现场生产环境要求&#xff0c;22端口在生产环境存在安全隐患&#xff09;&…

胜软科技冲刺北交所一年多转港股:由盈转亏,毛利率大幅下滑

《港湾商业观察》施子夫 近期&#xff0c;山东胜软科技股份有限公司&#xff08;以下简称&#xff0c;胜软科技&#xff09;递表港交所获受理&#xff0c;独家保荐机构为广发证券&#xff08;香港&#xff09;。 在赴港上市之前&#xff0c;胜软科技还曾谋求过A股上市&#x…

Java零基础入门笔记:多线程

前言 本笔记是学习狂神的java教程&#xff0c;建议配合视频&#xff0c;学习体验更佳。 【狂神说Java】Java零基础学习视频通俗易懂_哔哩哔哩_bilibili 第1-2章&#xff1a;Java零基础入门笔记&#xff1a;(1-2)入门&#xff08;简介、基础知识&#xff09;-CSDN博客 第3章…

数据类设计_图片类设计之1_矩阵类设计(前端架构基础)

前言 学的东西多了,要想办法用出来.C和C是偏向底层的语言,直接与数据打交道.尝试做一些和数据方面相关的内容 引入 图形在底层是怎么表示的,用C来表示 认识图片 图片是个风景,动物,还是其他内容,人是可以看出来的.那么计算机是怎么看懂的呢?在有自主意识的人工智能被设计出来…

C++:入门详解(关于C与C++基本差别)

目录 一.C的第一个程序 二.命名空间&#xff08;namespace&#xff09; 1.命名空间的定义与使用&#xff1a; &#xff08;1&#xff09;命名空间里可以定义变量&#xff0c;函数&#xff0c;结构体等多种类型 &#xff08;2&#xff09;命名空间调用&#xff08;&#xf…

linux下 jq 截取json文件信息

背景&#xff1a;通过‘登录名‘ 获取该对象的其他个人信息如名字。 环境准备&#xff1a;麒麟操作系统V10 jq安装包 jq安装包获取方式&#xff1a;yum install jq 或 使用附件中的rpm 或 git自行下载 https://github.com/stedolan/jq/releases/download/ 实现过程介绍&am…

软件工程:软件需求之需求分析方法

目录 前言 需求分析方法 工具和方法 具体分析方法 对运行环境的影响 ​编辑 前言 本文重点介绍开展软件需求分析的方法。 需求分析方法 工具和方法 软件需求可以维护在ALM系统中&#xff0c;譬如&#xff1a;doors&#xff0c;codeBeamer等&#xff0c;JIRA适合互联网行…

【网络编程】WSAAsyncSelect 模型

十、基于I/O模型的网络开发 接着上次的博客继续分享&#xff1a;select模型 10.8 异步选择模型WSAAsyncSelect 10.8.1 基本概念 WSAAsyncSelect模型是Windows socket的一个异步I/O 模型&#xff0c;利用这个模型&#xff0c;应用程序 可在一个套接字上接收以Windows 消息为基…

视觉-语言模型-出发点CLIP--(精读论文)

阅读建议&#xff1a;配合这个源码分析阅读效果更加 研究背景和目的 介绍当前计算机视觉系统依赖固定类别标签训练的局限性&#xff0c;以及自然语言监督作为一种有潜力替代方式的研究现状。强调论文旨在探索从自然语言监督中学习可迁移视觉模型&#xff0c;实现零样本学习&a…

任务11:路由器配置与静态路由配置

目录 一、概念 二、路由器配置 三、配置静态路由CSDN 原创主页&#xff1a;不羁https://blog.csdn.net/2303_76492156?typeblog 一、概念 1、路由器的作用&#xff1a;通过路由表进行数据的转发。 2、交换机的作用&#xff1a;通过学习和识别 MAC 地址&#xff0c;依据 M…

Python实例:PyMuPDF实现PDF翻译,英文翻译为中文,并按段落创建中文PDF

基于PyMuPDF与百度翻译的PDF翻译处理系统开发:中文乱码解决方案与自动化排版实践 一 、功能预览:将英文翻译为中文后创建的PDF 二、完整代码 from reportlab.lib.pagesizes import letter from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle

LeeCode题库第四十六题

46.全排列 项目场景&#xff1a; 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&am…

LangChain4j开发RAG入门示例

本文将详细介绍如何基于Java语言&#xff0c;使用Langchain4j开源框架、Milvus向量数据、阿里Qwen大模型&#xff0c;开发一个RAG入门级简单示例。本示例虽然简单&#xff0c;但涉及到多个知识点&#xff0c;包括&#xff1a;Milvus初始化、Embedding模型、文档切片、Springboo…

快速从C过度C++(一):namespace,C++的输入和输出,缺省参数,函数重载

&#x1f4dd;前言&#xff1a; 本文章适合有一定C语言编程基础的读者浏览&#xff0c;主要介绍从C语言到C过度&#xff0c;我们首先要掌握的一些基础知识&#xff0c;以便于我们快速进入C的学习&#xff0c;为后面的学习打下基础。 这篇文章的主要内容有&#xff1a; 1&#x…

课程《Deep Learning Specialization》

在coursera上&#xff0c;Deep Learning Specialization 课程内容如下图所示&#xff1a;