一、什么是命令(Command)模式

命令模式是行为型设计模式的一种,其目的是将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化。与另一种将每种命令与调用命令的对象结合形成一个专有类的方式相比,命令模式的优点有将调用操作的对象与知道如何实现该操作的对象解耦,增加新的命令不需要修改现有的类。

命令模式的结构如下:



参与者有:

1.Invoker请求者

要求该命令执行这个请求,即命令的调用者

2.Command接口

3.ConcreteCommand具体接口

4.Receiver接收者

命令的相关操作的实际实施者

5.Client

协作过程:

1.Client创建一个ConcreteCommand对象并指定它的Receiver对象

2.某Invoker对象存储该ConcreteCommand对象

3.该Invoker通过调用Command对象的Excute操作来提交一个请求。若该命令是可撤消的,ConcreteCommand就在执行Excute操作之前存储当前状态以用于取消该命令

4.ConcreteCommand对象对调用它的Receiver的一些操作以执行该请求

二、go-redis command相关代码

// commands.go

// Invoker请求者接口
type Cmdable interface {
Pipeline() Pipeliner
Pipelined(ctx context.Context, fn func(Pipeliner) error) ([]Cmder, error)
TxPipelined(ctx context.Context, fn func(Pipeliner) error) ([]Cmder, error)
TxPipeline() Pipeliner
Command(ctx context.Context) *CommandsInfoCmd
ClientGetName(ctx context.Context) *StringCmd
// ...
// 和所有Redis命令的相关方法
} // cmdable实现了Cmdable接口
type cmdable func(ctx context.Context, cmd Cmder) error
func (c cmdable) Echo(ctx context.Context, message interface{}) *StringCmd {
cmd := NewStringCmd(ctx, "echo", message)
_ = c(ctx, cmd)
return cmd
}

这里值得一提的是cmdable是一个函数类型,func(ctx context.Context, cmd Cmder) error

并且每个cmdable方法里都会有_ = c(ctx, cmd),也就是如何去调用cmd在这里还没有明确写出

再回头看redis.go,会发现这样一段代码

type Client struct {
*baseClient
cmdable
hooks
ctx context.Context
} func NewClient(opt *Options) *Client {
opt.init() c := Client{
baseClient: newBaseClient(opt, newConnPool(opt)),
ctx: context.Background(),
}
c.cmdable = c.Process //划线 return &c
}

c.cmdable = c.Process这行指定了请求如何调用Command的

在ctrl+左键追踪几层后,会在redis.go里找到调用的具体过程

// redis.go
func (c *baseClient) process(ctx context.Context, cmd Cmder) error {
......
err := cn.WithWriter(ctx, c.opt.WriteTimeout, func(wr *proto.Writer) error {
eturn writeCmd(wr, cmd)
}) err = cn.WithReader(ctx, c.cmdTimeout(cmd), cmd.readReply)
......

然后再去找Command,这边就比较清晰了,都在command.go中

// command.go

// Command接口
type Cmder interface {
Name() string
FullName() string
Args() []interface{}
String() string
stringArg(int) string
firstKeyPos() int8
setFirstKeyPos(int8) readTimeout() *time.Duration
readReply(rd *proto.Reader) error SetErr(error)
Err() error
} // 还有许多Cmder的具体实现,其中一个实现的部分代码如下
type XPendingExtCmd struct {
baseCmd
val []XPendingExt
}
func (cmd *XPendingExtCmd) Val() []XPendingExt {
return cmd.val
}

在这里没有看到Receiver,是因为每个Cmder实现都自己实现了所有功能,根本不需要额外的接收者对象。

三、总结

有时必须向某对象提交请求,但并不知道关于被请求的操作或请求的接受者的任何信息。这个时候可以用到命令模式,通过将请求本身变成一个对象来使工具箱对象可向未指定的应用对象提出请求。

命令模式与go-redis command设计的更多相关文章

  1. c#设计模式系列:命令模式(Command Pattern)

    引言 命令模式,我感觉"命令"就是任务,执行了命令就完成了一个任务.或者说,命令是任务,我们再从这个名字上并不知道命令的发出者和接受者分别是谁,为什么呢?因为我们并不关心他们是谁, ...

  2. 设计模式---行为变化模式之命令模式(Command)

    前提:行为变化模式 在组件的构建过程中,组建行为的变化经常导致组件本身剧烈的变化.“行为变化”模式将组件的行为和组件本身进行解耦,从而支持组件的变化,实现两者之间的松耦合. 类中非虚函数和静态函数方法 ...

  3. 命令模式(head first 设计模式5)

    一.命令模式定义 命令大家都不会陌生,那么在开始命令模式之前,可以想象一下生活中的命令模式的特点: 如老板命令你完成一个OA项目是一个命令,接着看看其特点: 1.在上面的命令中,命令的执行者肯定是聪明 ...

  4. C#设计模式学习笔记:(14)命令模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7873322.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第二个模式--命 ...

  5. OOP设计模式[JAVA]——04命令模式

    命令模式 命令模式的意图 命令模式属于对象的行为模式.别名又叫:Action或Transaction. 命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化,对请求 ...

  6. 设计模式(六):控制台中的“命令模式”(Command Pattern)

    今天的博客中就来系统的整理一下“命令模式”.说到命令模式,我就想起了控制台(Console)中的命令.无论是Windows操作系统(cmd.exe)还是Linux操作系统(命令行式shell(Comm ...

  7. (十三)WebGIS中工具栏的设计之命令模式

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 从这一章节开始我们将正式进入WebGIS的工具栏中相关功能的 ...

  8. C++设计模式-Command命令模式

    Command命令模式作用:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 由于“行为请求者”与“行为实现者”的紧耦合,使用命令模式 ...

  9. 深入浅出设计模式——命令模式(Command Pattern)

    模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请 ...

随机推荐

  1. 为什么类只能用public修饰?

    为什么类只能使用public修饰? 首先,类只能使用public修饰是一个伪命题,应该说我们只见到过使用public修饰的类,还有一些类没有访问修饰符,此时访问权限为default.其次,类实际上分为 ...

  2. 移动端 Swiper

    一.什么是swiper 开源.免费.强大的触摸滑动插件 Swiper常用于移动端网站的内容触摸滑动 Swiper能实现触屏焦点图.触屏Tab切换.触屏多图切换等常用效果 #二.如何使用 1.首先加载插 ...

  3. angular 8 表单带文件上传接口

    <div id="homework"> <form (ngSubmit)="doSubmit()" enctype="multipa ...

  4. Centos7.6上部署Supervisor来监控和操作各类服务

    supervisor    是用Python开发的一个client/server服务,是Linux/Unix系统下的一个进程管理工具,不支持Windows系统.它可以很方便的监听.启动.停止.重启一个 ...

  5. 用matlab提取jpg曲线数据或者jpg图片重新复原

    I = imread('111.jpg');%读取处理好的图片,必须是严格坐标轴线为边界的图片 I=rgb2gray(I); %灰度变化 I(I>200)=255; %二值化 I(I<=2 ...

  6. 安装篇九:安装wordpress(5.4版本)

    #1.下载wordpress程序 下载部署wordpress博客程序(https://cn.wordpress.org/ 英文官网:https://www.wordpress.org/ ) [root ...

  7. arp欺骗(理论)

    ARP(地址解析协议)在IPv4和以太网的广泛应用,其主要用作将IP地址翻译为以太网的MAC地址. 一.ARP通讯协议过程 局域网的通信不是根据IP地址进行,计算机是根据mac地址来识别一台机器. 每 ...

  8. java斐波纳契数列

    //斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1.1.2.3.5.8.13.21.-- 这个数列从第三项开始,每一项都等于前两项之和. public class DiGui { public ...

  9. java 反射给字段重新赋值

    1.获取实体的所有字段,遍历 2.获取字段类型 3.调用字段的get方法,判断字段值是否为空 4.如果字段值为空,调用字段的set方法,为字段赋值 Field[] field = model.getC ...

  10. 深入理解Redis系列之持久化

    redis持久化配置 redis.conf // RDB配置 save 900 1 save 300 10 save 60 10000 // AOF配置 appendonly yes //AOF三种同 ...