😊

Strategyパターンを使ったGoの実装について

に公開

Strategyパターンを使った実装をしたので、備忘録のため記事を書く。

Strategyパターンとは

振る舞いを動的に切り替えることを目的としたデザインパターン。具体的な処理をカプセル化し、インターフェースを通じて利用することで、処理の切り替えを柔軟に行えるようにする。
Goでは、インターフェースと構造体を使ってこのパターンを実現することができる。

具体例

料金計算ロジックを例に実装する。平日は通常料金だが、休日になると割増料金になるというルールを実装する。

具体ロジック

type FeeStrategy interface {
    Calculate(base int) int
}

type WeekdayStrategy struct {}
func (s WeekdayStrategy) Calculate(base int) int {
    return base
}

type HolidayStrategy struct{}
func (s HolidayStrategy) Calculate(base int) int {
	return base + 1000
}

呼び出し側

func main() {
    base := 5000
    strategy := SelectStrategy(time.Now())
    fee := strategy.Calculate(base)

    fmt.Println("料金:", fee)
}

func SelectStrategy(t time.Time) FeeStrategy {
    switch t.Weekday() {
    case time.Saturday, time.Sunday:
        return HolidayStrategy{}
    default:
        return WeekdayStrategy{}
    }
}

このようにインターフェースを通じて実装することで、Strategyパターンを実装できる。

また将来的に「水曜日だけ割引料金にしたい」などのルールが追加される場合は以下のように実装することで追加可能になる。

具体ロジック

type FeeStrategy interface {
    Calculate(base int) int
}

type WeekdayStrategy struct {}
func (s WeekdayStrategy) Calculate(base int) int {
    return base
}

type HolidayStrategy struct{}
func (s HolidayStrategy) Calculate(base int) int {
	return base + 1000
}

// 追加
type WednesdayStrategy struct{}
func (s WednesdayStrategy) Calculate(base int) int {
	return base - 2000
}

呼び出し側

func main() {
    base := 5000
    strategy := SelectStrategy(time.Now())
    fee := strategy.Calculate(base)

    fmt.Println("料金:", fee)
}

func SelectStrategy(t time.Time) FeeStrategy {
    switch t.Weekday() {
    case time.Wednesday: // 追加
        return WednesdayStrategy{}
    case time.Saturday, time.Sunday:
        return HolidayStrategy{}
    default:
        return WeekdayStrategy{}
    }
}

メリット

  • if文の乱立を避けれる(ifが深くならない)
  • ロジックごとのテストが簡単
  • 新しい条件が増えても既存コードに影響しない

Discussion