🔨

増補改訂版 Java言語で学ぶデザインパターン入門を読んだ感想

6 min read

こんにちは、VIC-Sといいます。Twitterもやってるので、よろしければフォローお願いします。→VICTOR-S

今回はJava言語で学ぶデザインパターン入門という書籍を読んだ感想を書きたいと思います。どうぞ最後までお付き合いください。

https://www.amazon.co.jp/増補改訂版-Java言語で学ぶデザインパターン入門-結城-浩-ebook/dp/B00I8ATHGW/ref=sr_1_1?__mk_ja_JP=カタカナ&dchild=1&keywords=デザインパターン&qid=1633791142&sr=8-1

はじめに

デザインパターンの書籍といえば通称GoF本と呼ばれる「オブジェクト指向における再利用のためのデザインパターン」が有名ですが、Kindle版が出てないことと、内容が分かりにくいという評判から「Java言語で学ぶデザインパターン入門」を読むことにしました。
Java言語で学ぶデザインパターン入門のKindle版は固定レイアウトとなっているので、表示崩れなどは起こりませんが、ハイライトや文字の拡大化などができないので読む場合は注意が必要です。
それでは各章ごとにコメント程度に述べていきたいと思います。

第1章 Iterator

様々な言語ですでに実装されているので、自分で書くことはないと思われるパターンです。つまり、それほど便利なパターンということだと思います。
Iteratorパターンは何かの集まりを1つずつ走査していくパターンです。パターン化することによって、何かの集まりは配列だけでなく、他の集合でも使用することができるようになるという所がデザインパターンらしいなと感じました。

第2章 Adapter

Adapterパターンは既存のクラスのままだと使えない場合に、そのズレを補うためのパターンです。Wrapperとも呼ばれています。
継承を使ったものと、委譲を使ったものがあります。どちらを使うかは好みでいいような気がします。

第3章 Template Method

名前の通り大枠のテンプレートを決めて、細かい部分をサブクラスを使って変更していくパターンです。クラス図もテンプレートを記述する抽象クラスと詳細を記述する実装クラスのみなので分かりやすいです。
便利で作成しやすいのでかなり使いやすいパターンではありますが、その分クラス間のつながりが強くなっています。Template Methodパターンは継承を使用しているパターンですが、似たようなパターンで委譲を使っているものにStrategyパターンがあるので、両パターンの使い所を考えていきたいです。

第4章 Factory Method

大枠はTemplate Methodと似た感じで、どんなインスタンスを生成するのかを詳細としてサブクラスで定義しているようです。
最初は使いみちがイマイチだったのですが、練習問題の解説でFactoryで生成されるクラスのコンストラクタをpublicにしないことで、他のクラスからのインスタンス生成を制限していてなるほどと思いました。

第5章 Singleton

今回のデザインパターンの中でダントツで分かりやすいパターンでした。インスタンスが1つであることを保証したいときなんかに使用すると効果的なパターンです。
Singletonパターンは実装も簡単で、使ったときの便利さも良いのですが、乱用するとグローバル変数の如く悪用されることもあるので使うときは注意が必要です。

第6章 Prototype

雛形となるインスタンスを作成し、その雛形をコピーしてインスタンスを使用するパターンです。
この本ではJava言語のCloneableインターフェイスやCloneメソッドを使用する前提ですので、実際のPrototypeパターンの実装について同じなのかは分かっていません。また、例ももう少し「このパターン使うと便利だな」と感じさせてくれると良かったなと思いました。

第7章 Builder

このパターンもIterator同様に様々なライブラリで使用されているパターンです。StringBuilderなんかで使用されいると思います。
パターンとしては、Builderインターフェイスで定義されているメソッドを使用することで、サブクラスごとにどのようなインスタンスにするか変えられることがメリットです。
例ではサブクラスのTextBuilderとHTMLBuilderで同じ引数を与えて、違う出力を出していました。これも継承を使用したオブジェクト指向らしいパターンだなと感じました。

第8章 Abstract Factory

この本の中で一番難しいパターンでした。何度か読み直していますが、ソラで説明できる自身はありません。
Factoryも作成するクラスも抽象化して、具体的にどんなクラスを作るかは具象クラスにすべてお任せするという汎用性に特化しまくったパターンです。具象Factoryに関しては、クラスの文字列からインスタンスを作成していたので、設定ファイルやコマンドライン引数で指定ができます。
実装部分を色々と対応する場合は便利そうですが、拡張に対して少し弱いので使いところが難しそうです。

第9章 Bridge

機能と実装を分割するパターンです。SOLID原則をほとんど網羅しているオブジェクト指向らしいパターンだなと思いました。
機能面の階層と実装面の階層に分かれていて、それぞれが実装を知らずに作ることができるので拡張に強いです。
デザインパターンというよりオブジェクト指向でのクラスの作り方に近いような気がするので、意識的に使っていきたいです。

第10章 Strategy

処理を委譲したサブクラスに任せるというこれもまたオブジェクト指向らしいパターンです。
Template Methodとは違い、処理の詳細をサブクラスではなく、委譲したクラスに行わせることでクラス間の結びつきを緩くすることができます。
処理によってアルゴリズムを変えるなどのプログラムでは効果を発揮するのではないでしょうか。

第11章 Composite

再帰構造を表現するのに便利なパターンです。
共通の親クラスComponentを継承し、Componentの集合を持っているのがComposite、持っていないのがLeafという役割のデザインパターンとなっています。
CompositeはAdd関数のようなLeafを追加する関数を持ちますが、LeafではAdd関数が実装されていないので、どのように実装するかで使い勝手が変わると思います。

第12章 Decorator

中身のオブジェクトにオプションを追加していくようなパターンです。
デザインパターンらしくどんなに付け足しても、最終的には親クラスで制御できるので、ポリモーフィズムの勉強にもなります。
例では文字列に枠を追加していましたが、実際に使うとしたらどういったケースがあるのか分からなかったので、ここも実践的な例が欲しかったです。

第13章 Visitor

このパターンも非常に複雑で、一度で理解するのは難しいです。
内容としてはデータ構造と処理を分離するためのパターンです。この本の例ではCompositeパターンで見てきたものの表示部分をVisitorパターンに置き換えたものでした。
複雑なパターンですが、データ構造と処理を分離しているので、処理に関しては追加がしやすくなっています。ただ、少しクラス間の結びつきが強い気がするので使い所がイマイチ分かっていません。

第14章 Chain of Responsibility

処理をクラスに分けて実装し、処理できないなら次のクラスにたらい回しにしていく感じのパターンです。パターンとしてはシンプルな方ですが、割と用途のあるパターンではないかなと感じています。
処理ごとにクラスを分けることで、処理が増えたときや、処理の変更をしたいときに他のクラスへの影響が少ないのがいいですね。

第15章 Facade

開発を進めていると様々なクラスが作られ、それらの使用順序やデータ取得の誓約などが出てくると思います。そんなものを隠蔽してくれるのがFacadeパターンです。
Facadeという聞き慣れない単語でパターン化されていますが、多分普通に使っていると思います。

第16章 Mediator

各クラス間がなんらかの状態で処理が変わる場合、Mediatorが状態ごとの処理を引き受けることで他のクラスが状態を知る必要がなくなるようになるパターンです。
例のGUIのログインフォームが分かりやすく、使いやすそうだったのでいつか使ってみたいなと思いました。
各クラスが状態ごとに処理を分ける必要がないので、それぞれ処理がシンプルになっていました。また、Mediatorに状態ごとの処理が集中しているためデバッグなどが楽になっているなと感じました。

第17章 Observer

観察対象のクラスの状態が変化すると、観察者に対して通知をして処理を行うパターンです。別名はPublish-Subscribeパターンで、こちらのほうがこのパターンの概要が分かりやすいと思います。
Mediatorも状態の変化に対応したパターンですが、Mediatorの場合は複数のクラスの状態を一括で管理するのに対し、Observerは各クラスが状態の変化を通知するというパターンとなっています。
現在ではModel/View/Controller(MVC)でよく使われているようです。

第18章 Memento

オブジェクトの状態を保存、取り出しを行うパターンです。
用途としてundo、redo、historyなどが挙げられていました。このあたりの処理としてはテキストエディターなどが思いつきますが、実際にMementoパターンは使用されているのかどうかが気になります。
パターンとしては結構シンプルですが、使い所はあまり多くはないと思います。

第19章 State

状態をオブジェクトとして扱い、ポリモーフィズムで状態ごとの処理を行うパターンです。
Stateを使用する側のクラスは状態ごとの内部の処理は知らなくてもいいので、情報の隠蔽がされている。このパターンもオブジェクト指向らしい良いパターンだと思います。
昔ゲーム開発で画面遷移の部分でStateパターンを使ったことがあります。インターフェイスは同じだけど、状態ごとで内部の処理が変わるという場合に非常に便利です。

第20章 Flyweight

再利用できるオブジェクトのインスタンスを共有するパターンです。
インスタンスを共有することで、インスタンスに変更が加わった場合は使われている箇所それぞれでに変更が及びます。この点は使い方によっては効果的に使えるのではないでしょうか。
しかし、オブジェクトを保持する都合上GCが走らないことや、使用している部分への影響が大きいことから微妙に使いにくそうなパターンだと感じました。

第21章 Proxy

オブジェクトを直接使うのではなく、間にProxyを挟んで使用するパターンです。
Proxyパターン自体は結構便利そうなパターンという印象を持ちましたが、いざ使用するかと考えると少し冗長かなと思います。
Proxyパターンの中にも種類があり以下のような分類がされています。

  • Virtual Prosy: インスタンスが必要になったときに生成し、利用します。
  • Remote Proxy: 使用するインスタンスがネットワークの向こう側など、遠い環境のインスタンスを利用する場合に使用します。
  • Access Proxy: 使用するインスタンスの機能を権限ごとに制限をかけるときに使用します。

第22章 Command

処理そのものをクラスとして実装し、Commandを実行するクラスはその処理におけるデータなどを切り離すことができるパターンです。
この書籍の例はCommandパターンの実装部分にCompositeパターンも含まれており、Commandパターン自体の説明としては少し分かりにくかったです。Commandパターン自体の説明は「アジャイルソフトウェア開発の奥義」という書籍のほうが分かりやすかったと思います。

第23章 Interpreter

文法を解析して構文木を作成し、実行するパターンです。
最初に名前を見たときはインタプリタ型言語と似てるなと思ったのですが、パターンの説明読んだらまさにその言語の作り方だったので、知らずに恥をかかずに済みました。
練習問題がこれまでに出てきたパターンを組み合わせてプログラムを作成していたので、とても勉強になりました。

まとめ

デザインパターンを勉強したことでオブジェクト指向についての理解度がさらに高まったと思います。デザインパターンのプログラム例を見るだけでも新しい発見やオブジェクト指向プログラムの方法を知ることができるので読んでいて面白かったです。また、オブジェクト指向の原則などを頭の片隅に置きながら読むとより一層勉強になると思います。

ここまで読んでいただき、ありがとうございました。

Discussion

ログインするとコメントできます