Go设计模式之策略模式

194 阅读2分钟

策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时选择算法的行为,并将其封装在一个指定的算法类中。这种模式可以使得算法的选择独立于使用它的客户代码。

应用场景

当需要在运行时选择不同的算法时,可以使用策略模式。在以下场景中,策略模式特别有用:

  • 当类中有许多与某个行为相关的条件语句时;
  • 当需要在不影响其他代码的情况下轻松更改算法时;
  • 当类中有许多if-else语句时,应该使用这个模式。

实现

在实现策略模式时,需要考虑以下角色:

  • Context: 上下文,包含策略的引用并且执行与策略关联的操作;
  • Strategy: 策略,定义一个接口,用于所有支持算法的类的公共处理;
  • ConcreteStrategy: 具体策略,提供策略的具体实现。

下面是一个示例代码:

package main

import (
	"fmt"
)

type PaymentContext struct {
	Name, CardNumber, Date string
	Amount                 float32
	strategy               PaymentStrategy
}

func NewPaymentContext(name, cardNumber, date string, amount float32, strategy PaymentStrategy) *PaymentContext {
	return &PaymentContext{
		Name:      name,
		CardNumber: cardNumber,
		Date:      date,
		Amount:    amount,
		strategy: strategy,
	}
}

func (c *PaymentContext) SetStrategy(strategy PaymentStrategy) {
	c.strategy = strategy
}

func (c *PaymentContext) Pay() {
	fmt.Printf("Customer: %s, CardNumber: %s, Date: %s, Amount: %f\n", c.Name, c.CardNumber, c.Date, c.Amount)
	c.strategy.Pay(c.Amount)
}

type PaymentStrategy interface {
	Pay(float32)
}

type CreditCardStrategy struct{}

func (s *CreditCardStrategy) Pay(amount float32) {
	fmt.Printf("Credit Card payment amount: %f\n", amount)
}

type PayPalStrategy struct{}

func (s *PayPalStrategy) Pay(amount float32) {
	fmt.Printf("PayPal payment amount: %f\n", amount)
}

func main() {
	creditCardStrategy := &CreditCardStrategy{}
	paypalStrategy := &PayPalStrategy{}

	context := NewPaymentContext("John", "123456789", "01/01/2022", 100.0, creditCardStrategy)
	context.Pay()

	context.SetStrategy(paypalStrategy)
	context.Pay()
}

在上面的代码中,Context实现了策略模式的关键概念之一,它仅包含策略的引用,并将其传递给实现策略接口的具体函数。具体的策略实现在ConcreteStrategy中。

总结

策略模式是一种简单但非常强大的设计模式。它将算法的选择与使用它的客户代码分离,并使得更改算法变得容易。这种模式可以改进代码的可维护性,并提高代码的复用性。在Go中,使用策略模式需要特别注意接口的使用,以实现不同的策略。