如何在Go语言中实现策略模式?

10

以下是需要翻译的内容:

这是我试图解决的一般性问题:

  1. 一个程序包从一个数据源收集数据并将其发送到多个渠道。
  2. 第二组程序包从多个渠道收集数据并将其写入一个数据源。此组程序包需要将数据从多种格式转换为目标格式。

这似乎是策略模式的完美案例,但我不确定如何在Go中最好地实现它。

3个回答

22

一般来说,构建Go应用程序时不要迷失于模式和协议中。该语言使得表达和直截了当变得容易。大多数情况下,定义稳定的接口足以使所有东西变得足够灵活。

但是,这里有一个关于Go策略模式的例子:

为策略的行为定义一个接口:

type PackageHandlingStrategy interface {
    DoThis()
    DoThat()
}

执行该策略:

type SomePackageHandlingStrategy struct {
    // ...
}

func (s *SomePackageHandlingStrategy) DoThis() {
    // ...
}

func (s *SomePackageHandlingStrategy) DoThat() {
    // ...
}

然后,要么嵌入…

type PackageWorker struct {
    SomePackageHandlingStrategy
}

func (w *PackageWorker) Work() {
    w.DoThis()
    w.DoThat()
}

…或者通过策略…

type PackageWorker struct {}

func (w *PackageWorker) Work(s PackageHandlingStrategy) {
    s.DoThis()
    s.DoThat()
}

… 给你的工人。


非常好的回答,谢谢!不是因为我知道这个问题在某种程度上已经得到解决,所以我并没有迷失在模式中。再次感谢。 - KevDog
1
但是如何动态加载策略呢?如果我需要根据站点中的配置加载策略,那么在Go中该怎么做呢?从我所看到的来看,在Golang中没有办法动态加载包。或者还有其他方法吗? - Madhan Ganesh
2
@Madhan 使用 switch 语句。 - thwd
@madhan 你可以创建一个策略工厂。然后从配置中传递策略名称,工厂将创建所需的策略实例。工厂可以使用 switch 或 map[string]Strateger 实现。 - Dr.eel

1

@madhan 您可以创建一个策略工厂。然后从配置中传递策略名称,工厂将创建您需要的策略实例。工厂可以使用 switch 或 map[string]Strateger 实现。


0
请看下面的另一个例子。
// Duck embeds IQuack interface
// Client for IQuack behavior
type Duck struct {
    IQuack
}

// IQuack is interface for quacking behavior (Behavior)
type IQuack interface {
    Quack() string
}

// NoQuacking implements IQuack interface and does not quack.
// Concrete Behavior
type NoQuacking struct{}

// Quack returns "I cannot Quack"
func (i NoQuacking) Quack() string {
    return "I cannot Quack :("
}

// LoudQuacking implements IQuack interface and is for ducks that quack loudly.
// Concrete Behavior
type LoudQuacking struct{}

// Quack returns "I Quack loudly"
func (i LoudQuacking) Quack() string {
    return "I Quack loudly!!"
}

// ShyQuacking implements IQuack interface and is for ducks that are shy.
// Concrete Behavior
type ShyQuacking struct{}

// Quack returns "I do a shy quack"
func (i ShyQuacking) Quack() string {
    return "I do a shy quack :)"
}

func main() {
    rubberDuck := Duck{NoQuacking{}}
    fmt.Println(rubberDuck.Quack)

    wildDuck := Duck{LoudQuacking{}}
    fmt.Println(wildDuck.Quack)
}

在这个例子中,Duck 是客户端。
它有一个IQuack的行为(接口)。“NoQuacking”、“LoudQuacking”和“ShyQuacking”是实现IQuack接口的算法/具体行为。
因此,鸭子可以使用“NoQuacking”、“LoudQuacking”或“ShyQuacking”算法交替地进行quack()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接