0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go | Strategy + Null Object

Last updated at Posted at 2024-07-30

雑めも

  • ストラテジーパターン

    • アルゴリズム(ストラテジー)を注入して使う。Excelストラテジー、PDFストラテジー、Nilストラテジーのどれか。
    • それぞれのストラテジーごとに、構造体が違うため保持できるデータも異なる(Excel.excelPdf.pdf の箇所)
  • Null Object

    • Nilストラテジーは Null Objectパターンで、nil ではなくて処理をしない構造体を渡しておくと実行時に nil チェックが必要なくなる
  • インジェクション

    • ストラテジーを注入するタイミングがコンストラクタによる生成時かメソッドを実行時によってやり方が異なる

ストラテジーパターン(コンストラクタインジェクション)

package main

import "fmt"

func main() {
	var ct Content

	// Excel
	ct = Content{Name: "file1.xlsx", Data: Excel{}}
	ct.Load()
	ct.Print()

	// Pdf
	ct = Content{Name: "file2.pdf", Data: Pdf{}}
	ct.Load()
	ct.Print()

	// Null
	ct = Content{Name: "unknown", Data: Nil{}}
	ct.Load()
	ct.Print()
}

// Content
//
// ファイルに対するラッパー.
type Content struct {
	Name string
	Data ExcelOrPdf
}

func (c Content) Load()  { c.Data.Load() }
func (c Content) Print() { fmt.Println(c.Name, c.Data.Text()) }

// ストトラテジーのInterface
type ExcelOrPdf interface {
	Load()
	Text() string
}

// Excel
//
// Excel ストラテジー
type Excel struct {
	excel int64 // excel のライブラリのデータを入れる
}

func (e Excel) Load() { fmt.Println("Excel load") }

func (e Excel) Text() string { return "Excel print done" + string(e.excel) }

// PDF
//
// PDF ストラテジー
type Pdf struct {
	pdf string // pdf のライブラリのデータを入れる
}

func (p Pdf) Load() { fmt.Println("PDF load") }

func (p Pdf) Text() string { return "PDF print done" + p.pdf }

// Nil
//
// NullObject ストラテジー
type Nil struct{}

func (n Nil) Load() { fmt.Println("<Nil load>") } // noop

func (p Nil) Text() string { return "<Nil print done>" } // noop

ストラテジーパターン(メソッドインジェクション)

package main

import "fmt"

func main() {
	var ct Content

	// Excel
	ct = Content{Name: "file1.xlsx"}
	excel := Excel{}
	ct.Load(excel)
	ct.Print(excel)

	// Pdf
	ct = Content{Name: "file2.pdf"}
	pdf := Pdf{}
	ct.Load(pdf)
	ct.Print(pdf)

	// Null
	ct = Content{Name: "unknown"}
	it := Nil{}
	ct.Load(it)
	ct.Print(it)
}

type Content struct {
	Name string
}

// Load
type Loader interface{ Load() }

func (c Content) Load(loader Loader) { loader.Load() }

// Print
type Texter interface{ Text() string }

func (c Content) Print(texter Texter) { fmt.Println(c.Name, texter.Text()) }

// Excel
//
// Excel ストラテジー
type Excel struct {
	excel int64 // excel のライブラリのデータを入れる
}

func (e Excel) Load() { fmt.Println("Excel load") }

func (e Excel) Text() string { return "Excel print done" + string(e.excel) }

// PDF
//
// PDF ストラテジー
type Pdf struct {
	pdf string // pdf のライブラリのデータを入れる
}

func (p Pdf) Load() { fmt.Println("PDF load") }

func (p Pdf) Text() string { return "PDF print done" + p.pdf }

// Nil
//
// NullObject ストラテジー
type Nil struct{}

func (n Nil) Load() { fmt.Println("<Nil load>") } // noop

func (p Nil) Text() string { return "<Nil print done>" } // noop

所感

  • Goだとおそらくメソッドインジェクションが多い印象
    • Load / Print において、それぞれのInterfaceを切り出すこともできる
    • またレイヤーが浅くなるのでシンプルになる
    • ただ、今回の場合はexcel/pdfなどの情報を使い回すので Content の中に入れておけるコンストラクタインジェクションの方が良さそう
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?