Go中的装饰器功能

xpt*_*xpt 9 design-patterns decorator go demo

装饰模式(功能)有许多好处:

当一个方法有许多正交问题时,这是非常有用的...即,这些问题都不相关,除了我们想要在我们调用方法时做所有(或一些)它们.这是装饰模式真正有用的地方.

通过实现装饰器模式,我们订阅了open-closed主体.我们的方法对未来的扩展开放,但对未来的修改是封闭的.遵守开放封闭原则有很多令人遗憾的好处.

但是,我发现的所有示例都非常复杂(例如,编写带有许多中间件的HTTP服务器).这使我很难将原则应用于其他地方.我需要一些我可以轻松尝试的东西,以便绕过它.

有人能给我一个更简单的例子,可以最好地说明如何在Go中做装饰模式(函数)吗?

Alex Alehano的这个例子太简单了,不能投入实际使用.我需要能够说明这一点的东西:

func Decorate(c Decorated, ds ...Decorator) Decorated {
    decorated := c
    for _, decorate := range ds {
        decorated = decorate(decorated)
    }
    return decorated
}
Run Code Online (Sandbox Code Playgroud)

根据不同选项/指令的字符串操作,例如,对于upper,to lower,to base64等,将是IMO的最佳示例,并且还添加前缀/后缀,因为" 如果装饰器本身被参数化,则该技术被证明是特别有价值的. ".

mko*_*iva 11

首先,装饰器基本上是一个函数,它将特定类型的另一个函数作为其参数,并返回相同类型的函数.这基本上允许您创建一系列功能.所以在Go中它看起来像这样:

// this is the type of functions you want to decorate
type StringManipulator func(string) string

// this is your decorator.
func ToLower(m StringManipulator) StringManipulator {
    return func(s string) string {
        lower := strings.ToLower(s)
        return m(lower)
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个更完整的例子


syn*_*gma 7

根据不同的选项/指令进行字符串操作,例如,上、下、添加前缀/后缀、base64 等,将是 IMO 的最佳示例。

这是您询问的示例:

package main

import (
    "fmt"
    "strings"
)

const (
    prefix = "PREFIX"
    suffix = "SUFFIX"
)

type Decorated=string

func addConstPrefix(s string) string {
    return prefix + s
}

func addConstSuffix(s string) string {
    return s + suffix
}

type Decorator=func(string) string

func Decorate(c Decorated, ds ...Decorator) Decorated {
    decorated := c
    for _, decorator := range ds {
        decorated = decorator(decorated)
    }
    return decorated
}

func main() {

    var toLower Decorator = strings.ToLower
    var toUpper Decorator = strings.ToUpper
    var dec3 Decorator = addConstPrefix
    var dec4 Decorator = addConstSuffix

    input := "Let's decorate me!"
    inputUppercase := Decorate(input, []Decorator{toUpper}...)
    fmt.Println(inputUppercase)

    allDecorators := []Decorator{toUpper, toLower, dec3, dec4}
    output := Decorate(input, allDecorators...)
    fmt.Println(output)
}
Run Code Online (Sandbox Code Playgroud)

请注意,为了简单起见,它使用了 Go 1.9 中引入的Golang类型别名。这是我们使用的两个别名:

type Decorated=string
type Decorator=func(string)string
Run Code Online (Sandbox Code Playgroud)

以便Decorate()以后可以应用您的功能。然后我们简单地创建几个与我们定义的类型签名匹配的装饰器(函数):

var toLower Decorator = strings.ToLower
var toUpper Decorator = strings.ToUpper
var dec3 Decorator = addConstPrefix
var dec4 Decorator = addConstSuffix
Run Code Online (Sandbox Code Playgroud)

并应用它们:

allDecorators := []Decorator{toUpper, toLower, dec3, dec4}
output := Decorate(input, allDecorators...)
Run Code Online (Sandbox Code Playgroud)

编辑:

参数化装饰将仅仅是返回另一个函数,例如函数:

func addPrefix(prefix string) func(string) string {
    return func(s string) string {
        return prefix + s
    }
}
Run Code Online (Sandbox Code Playgroud)

然后可以通过以下方式应用它:

input2 := "Let's decorate me!"
prefixed := Decorate(input2, []Decorator{addPrefix("Well, ")}...)
Run Code Online (Sandbox Code Playgroud)