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

huangapple go评论111阅读模式
英文:

How to implement Strategy Pattern in Go?

问题

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

  1. 一组包从一个来源收集数据并将其发送到多个通道。
  2. 另一组包从多个通道收集数据并将其写入一个来源。这组包需要将数据从多种格式转换。

这似乎是使用策略模式的完美案例,但我不确定如何在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.

答案1

得分: 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()
}

...给你的工作者。

英文:

In general; don't get lost in patterns and protocols to build Go applications. 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:

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.

答案2

得分: 1

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

英文:

@madhan You can make a factory of strategies. 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.

答案3

得分: 0

请参考下面的另一个示例。

// Duck嵌入了IQuack接口
// IQuack行为的客户端
type Duck struct {
    IQuack
}

// IQuack是quacking行为的接口(行为)
type IQuack interface {
    Quack() string
}

// NoQuacking实现了IQuack接口,不会quack。
// 具体行为
type NoQuacking struct{}

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

// LoudQuacking实现了IQuack接口,用于大声quack的鸭子。
// 具体行为
type LoudQuacking struct{}

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

// ShyQuacking实现了IQuack接口,用于害羞的鸭子。
// 具体行为
type ShyQuacking struct{}

// Quack返回"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行为(接口)。NoQuackingLoudQuackingShyQuacking是实现IQuack接口的算法/具体行为。

因此,鸭子可以使用NoQuacking / loudQuacking / ShyQuacking算法来quack()

英文:

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.

It has an IQuack behavior (interface). NoQuacking, LoudQuacking, ShyQuacking are the algorithms/concrete-behavior that implement the IQuack interface.

A Duck can thus quack() using the NoQuacking / loudQuacking / ShyQuacking algorithm interchangeably.

huangapple
  • 本文由 发表于 2013年7月22日 22:00:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/17789527.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定