简体   繁体   English

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

[英]How to implement Strategy Pattern in Go?

Here's the the general problem I am trying to solve:这是我要解决的一般问题:

  1. One set of packages is collecting data from one source and sending it to many channels.一组包从一个来源收集数据并将其发送到多个渠道。
  2. A second set of packages is collecting data from many channels and writing it to one source.第二组包是从许多渠道收集数据并将其写入一个源。 This set of packages would need to translate data from multiple formats.这组包需要翻译多种格式的数据。

This seems like a perfect case for the Strategy Pattern but am not sure how best to make that work in Go.这似乎是策略模式的完美案例,但不确定如何最好地在 Go 中发挥作用。

In general;一般来说; don't get lost in patterns and protocols to build Go applications.不要迷失在构建 Go 应用程序的模式和协议中。 The language makes it easy to be expressive and straightforward.该语言使其易于表达和直截了当。 Most of the time defining solid interfaces makes everything flexible enough.大多数情况下,定义可靠的接口使一切都足够灵活。

Still, here's an example of the strategy pattern in Go:不过,这里有一个 Go 中策略模式的例子:

Define an interface for the behavior of the strategies:为策略的行为定义一个接口:

type PackageHandlingStrategy interface {
    DoThis()
    DoThat()
}

Implement that strategy:实施该策略:

type SomePackageHandlingStrategy struct {
    // ...
}

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

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

And then, either embed…然后,要么嵌入......

type PackageWorker struct {
    SomePackageHandlingStrategy
}

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

…or pass the strategy… ……或者通过策略……

type PackageWorker struct {}

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

… to your worker. ……给你的工人。

@madhan You can make a factory of strategies. @madhan 您可以制作策略工厂。 Then pass the strategy name from the config, the factory will create the instance of the strategy you need.然后从配置中传递策略名称,工厂将创建您需要的策略实例。 Factory can be implemented with switch or map[string]Strateger.工厂可以用 switch 或 map[string]Strateger 实现。

Please see another example below.请参阅下面的另一个示例。

// 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)
}

In the example, the Duck is the client.在示例中, Duck是客户端。

It has an IQuack behavior (interface).它有一个IQuack行为(接口)。 NoQuacking , LoudQuacking , ShyQuacking are the algorithms/concrete-behavior that implement the IQuack interface. NoQuackingLoudQuackingShyQuacking是实现 IQuack 接口的算法/具体行为。

A Duck can thus quack() using the NoQuacking / loudQuacking / ShyQuacking algorithm interchangeably.因此,Duck 可以交替使用NoQuacking / loudQuacking / ShyQuacking算法来quack()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM