【デザインパターン】Go言語で再考するAbstract Factory


Abstract Factoryパターンを一言で!

インスタンスの生成(New)を全てインスタンス生成工場に任せるパターン

ソースコードは以下のリポジトリを参照してください。
https://github.com/yoshinorihisakawa/design-pattern/tree/master/abstract-factory

Abstract Factoryパターンが使えるシチュエーション

  • 使う側の修正を少なく、インスタンスを生成を切り替えたい
  • 複数のオブジェクト群を間違いなく生成したい

※本来Abstract Factoryパターンは後者の複数のオブジェクト群の生成を一つの工場に任せて生成させるパターンですが、工場をうまく切り替えて製品を生成する方法(strategyのような)の方が実用的かと思います。なのでこの記事ではそれを考慮したものになっております。

Abstract Factoryパターンを詳しく解説

Abstract Factoryパターンでは、抽象的な工場と、抽象的な部品を組み合わせて、抽象的な製品を作っていきます。
抽象的?と疑問を持たれたかもしれないので、抽象的という言葉について、一度定義しておきます。
抽象的とは、「具体的な実装のことは考えずに、インタフェースや抽象メソッドだけについて考えること」とします。
抽象的な部品を使って組み立てることで、使う人が具体的な実装には知らなくて良い状態になります。
言い換えると、こっそり具体的な実装を修正しても使う人はその修正を気にする必要が無くなります。
つまり、「使う人」と「実装」の依存関係が浅くなり、変更に強いプログラムを作ることができるのです。

それではAbstract Factoryパターンを使った場合、使わなかった場合を比較して見ていきます。

Abstract Factoryパターンを不採用

例えば、Mysqlを生成し、使う場合もあれば、Postgresを生成し使う場合の2パターンがあるとします。
処理を切り替える場合は、以下のように生成する処理を書き換える必要があります。

// mysql
Mysql m = NewMysql();
m.hogehoge()

// Postgres
Postgres p = NewPostgres();
p.hogehoge()

Abstract Factoryパターンを採用

上記の処理をAbstract Factoryパターンを採用したらどのようなコードになるか見ていきます。

// mysql
Factory f = NewFactory(Mysql)
Db db = f.getDb()
db.hogehoge()

// Postgres
Factory f = NewFactory(Postgres)
Db db = f.getDb()
db.hogehoge()

Abstract Factoryパターンを採用したコードでは、引数を変更するだけで、
MysqlからPostgresへ変更する事ができました。
このようにインタフェースなどを用いて、使う側に依存のないコードを書くようにすると変更に強いプログラムを作る事でできます。

UMLでイメージを掴む

よく出回っているのでこちらのクラス図を参照
http://www.techscore.com/tech/DesignPattern/AbstractFactory.html/

実装してみる

以下のリポジトリにAbstract Factoryパターンを実装したソースを載せておきました。
https://github.com/yoshinorihisakawa/design-pattern/tree/master/abstract-factory

抽象と具象の境界を意識してコードリーディングをするとわかりやすいかもしれません。

最後に

Abstract Factoryパターンは比較的シンプルなデザインパターンなので、
積極的に実戦で使っていけるパターンだと思いました。