NAKKA-Kの技術ブログ

技術に関する知見や考え方などを投稿します。

「HeadFirstデザインパターン」のStrategyパターンをGo言語で実装してみた

「HeadFirstデザインパターン」ではJavaを用いてデザインパターンの実装が解説されています。 これらのデザインパターンをGo言語で実験的に設計し直した実装を紹介します。

Strategyパターンとは

簡単な概要だけを説明すると、

複数の振る舞いをインターフェース化し、特定のクラスにメンバ変数として持たせます。 それにより特定のクラスの内容を変更することなく、動的に振る舞いを変えることができるパターンです。

想定

複数種類の鴨を実装します。 それぞれの鴨が、飛んだり飛ばなかったり、鳴いたり鳴かなかったりします。

これをもし鴨という親クラスと鴨A・鴨Bと継承して、それぞれに飛ぶ処理や飛ばない処理を実装するのが単純な方法かもしれません。 オブジェクト指向を始めたばかりに多い実装だと思います。

ですがそれでは同じ飛ぶ処理を持つ鴨が出てきて、実装が重複する可能性が高くなります。 また、動的に変更することもできません。

これをStrategyパターンを使って実装するという想定です。 詳細を知りたい場合は書籍を読んでください。

Go言語での実装

今回のコードは全てGitHubのリポジトリにありますので、全体のソースコードはそちらからご覧ください。

飛ぶインターフェースを実装した振る舞い構造体を用意します。

同じく鳴くインターフェースを実装した振る舞い構造体を用意します。

鴨の実装は少し複雑です。

duck構造体は、全ての鴨が持つべき共通処理と振る舞い構造体(*Behavior)を持っています。 この構造体は抽象クラスのように使うつもりなのでprivateで定義しています。 具体的な鴨はDuckインターフェースを実装し、型の統一をします。

具体的な鴨の実装であるMallardDuck構造体に、duck構造体を委譲します。 これによりクラスの継承に似た状況を作り出します。

鴨たちが持つ飛行・鳴き声の振る舞い構造体は実行時に生成し、それぞれの鴨に渡しています。 そして、Duckインターフェースを実装しています。

これが鴨Strategyパターンの動作イメージです。 Duckインターフェースを実装した鴨たちのコンストラクタ関数を呼び出して配列を初期化します。 それをループで回して正常に動くことを確認するコードです。

まとめ

飛んだり鳴いたりする振る舞いを抽出し、鴨の共通構造体に持たせる。 具体的な鴨に共通構造体を委譲し、インターフェースを実装する。

これにより振る舞いは柔軟に変更でき、実装の重複が少なくなります。 そしてインターフェースへプログラミングすることによって自由な取り回しが可能です。

この実装が実戦で使えるかと言われるとわかりませんが、設計とはカスタマイズするためにあるのでいろいろ試してましょう。

Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本

Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本

この本のデザインパターンを順次試していく予定なので、次回もどうぞご覧ください。

nakka-k.hatenablog.com

参考

Strategy パターン - Wikipedia