dushaoshuai / dushaoshuai.github.io

https://www.shuai.host
0 stars 0 forks source link

Factory Method #77

Open dushaoshuai opened 1 year ago

dushaoshuai commented 1 year ago

工厂方法模式简单说就是不同类型实现同一个接口,客户代码操作接口,而不是接口的具体实现。

一个简单的实现

一个简单的实现

github.com/redis/go-redis

go-redis 使用工厂方法模式创建对象。

首先定义了一个接口 Cmder

type Cmder interface {
    Name() string
    FullName() string
    Args() []interface{}
    String() string
    stringArg(int) string
    firstKeyPos() int8
        // ...
}

baseCmd 实现了某些方法,但没有实现 Cmder

type baseCmd struct {
    ctx    context.Context
    args   []interface{}
    err    error
    keyPos int8

    _readTimeout *time.Duration
}

func (cmd *baseCmd) Name() string {
    if len(cmd.args) == 0 {
        return ""
    }
    // Cmd name must be lower cased.
    return internal.ToLower(cmd.stringArg(0))
}

func (cmd *baseCmd) Args() []interface{} {
    return cmd.args
}
// ...

baseCmd 被嵌入其他类型,为他们提供一些公共方法,减少代码重复:

type Cmd struct {
    baseCmd

    val interface{}
}

func NewCmd(ctx context.Context, args ...interface{}) *Cmd {
    return &Cmd{
        baseCmd: baseCmd{
            ctx:  ctx,
            args: args,
        },
    }
}

// ...

type SliceCmd struct {
    baseCmd

    val []interface{}
}

func NewSliceCmd(ctx context.Context, args ...interface{}) *SliceCmd {
    return &SliceCmd{
        baseCmd: baseCmd{
            ctx:  ctx,
            args: args,
        },
    }
}

// ...

type StatusCmd struct {
    baseCmd

    val string
}

func NewStatusCmd(ctx context.Context, args ...interface{}) *StatusCmd {
    return &StatusCmd{
        baseCmd: baseCmd{
            ctx:  ctx,
            args: args,
        },
    }
}

// ...

CmdSliceCmdStatusCmd 都实现了 Cmder,且都有自己的构造函数。

See also