「初心者のためのデザインパターン入門」シリーズ 第0回 【デザインパターンとは?】
始めに
本記事は当ブログ管理人よしたろうによる『GoFデザインパターン入門シリーズ』です。本記事を見るだけで、各デザインパターンの総合的理解ができることをコンセプトにしております。ピンポイントな情報ではなく、理解に必要な周辺知識をできる限り記述していきます。一記事あたりの文章量は多くなる傾向になります。あまりそういった記事が見当たらないこと、自身の学習のためにそういった形式にしております。以前の記事で詳しく紹介した部分はリンクの引用をする場合もあります。
こちらの記事では以下の流れでデザインパターンの解説を行なっています。
この中で最も重要なのは以下のふたつ
です。また、
では、
についてもtwadaさんの解説をまとめ、加筆しました。 こちらもオブジェクト指向を理解する上で必須な思考だと思います。
- デザインパターンとは何か?
- GoFデザインパターンの教え
- 1995年登場時のGoFデザインパターンの立ち位置【リファクタリングと自動テストがなかった時代】
- 現代のGoFデザインパターンの立ち位置【リファクタリングと自動テストが登場してから】
- 現在においてもデザインパターンは有用か?
- UML
- プログラムを完成品としてみない
デザインパターンはクラスの再利用化を促進するものです。 再利用化を促進するとは、 クラスを部品として使えるようにするということであり、1つの部品を修正しても、他の部品の修正が少なくてすむ、ということなのです。
GoFのデザインパターンは1995年に生まれました。現在とは全く違う時代背景のコンテキスト(文脈・前提条件)に沿って発生する、問題課題に提示されたソリューションです。当然、現代にそれがそのまま当てはまるわけではありません。
しかしながら、現代でもGoFデザインパターンは非常に有用なものであることは間違いありません。 特に、上記で挙げている「現代におけるGoFデザインパターンの現代の立ち位置」、及び「2009年に行われた再定義」は今からデザインパターンを学ぶ人は絶対に知っておかなければいけない事柄だと思います。なかなか出てこない話をまとめました。
主なソースはtwadaさんのPodcastです。
- 始めに
1. デザインパターンとは何か?
1-1. 引用:「Java言語で学ぶデザインパターン入門」
プログラミングを行っていると、以前と同じことを繰り返しているなあ、と気づくときがあります。経験が増すにつれ、そのような 「パターン」が自分の心の中に数多く蓄積され、やがてその「パターン」を次の開発に当てはめていくことができるようになります。
Erich Gamma, Richard Helm, Ralph Johnson, John Vlissidesの4人が、そのような開発者の 「経験」や 「内的な蓄積」としてのパターンを「デザインパターン」 という形に整理しました。 この4人は、 the Gang of Four あるいはGoFと呼ばれています。 GoF は、 よく使われる23個のデザインパターンに「名前」を与え、 「カタログ」として 整理し、 1冊の本にまとめました。 この本が 『オブジェクト指向における再利用のための デザインパターン』 (付録D [GoF] 参照)です。
また、単に「デザインパターン」という場合、この23個のパターンを指す場合もあるようで、非常に有名なパターンとして広く知られているとのこと。 こちらの書籍に乗ってある文言だけみても、ジュニア層にとって金言なのではないでしょうか?ここだけでDRY原則・単一責任原則のエッセンスがあるような気がします。
1-2. GoF本内にあるデザインパターン23種類のカテゴライズ
参考:
PHPによるデザインパターン入門 - 目次 - Do You PHP はてブロ
パターン名 | 目的 | 使い所 |
---|---|---|
オブジェクトの生成に関するパターン | ||
Abstract Factory (関連する部品を組み合わせて製品を作る) | 互いに関連したり依存し合うオブジェクト群を、その具象クラスを明確にせず生成するためのインタフェースを提供する。 | オブジェクトの生成を条件によって分岐したい時。 |
Builder(複雑なインスタンスを組み立てる) | 複合オブジェクトについて、その作成過程を表現形式に依存しないものにすることにより、同じ作成過程で異なる表現形式のオブジェクトを生成できるようにする。 | オブジェクトの初期化を条件によって分岐したい時。 |
Factory Method(インスタンス作成をサブクラスにまかせる) | オブジェクトを生成するときのインタフェースだけを規定して、実際にどのクラスをインスタンス化するかはサブクラスが決めるようにする。Factory Methodパターンは、インスタンス化をサブクラスに任せる。 | オブジェクトの生成、初期化を条件によって分岐したい時。生成をクラスで分けるほど複雑でない時。 |
Prototype(コピーしてインスタンスを作る) | 生成すべきオブジェクトの種類を原型となるインスタンスを使って明確にし、それをコピーすることで新たなオブジェクトの生成を行う。 | オブジェクトを状態含めてクローンしたい時。 |
Singleton(たった1つのインスタンス) | あるクラスに対してインスタンスが1つしか存在しないことを保証し、それにアクセスするためのグローバルな方法を提供する。 | オブジェクトが複数あって欲しくない時。 |
プログラムの構造に関するパターン | ||
Adapter(一皮かぶせて再利用) | あるクラスのインタフェースを、クライアントが求める他のインタフェースへ変換する。Adapterパターンは、インタフェースに互換性のないクラス同士を組み合わせることができるようにする。 | 編集できないインタフェースを求める形に変換したい時。 |
Bridge(機能の階層と実装の階層を分ける) | 抽出されたクラスと実装を分離して、それらを独立に変更できるようにする。 | 実装クラスと拡張クラスを自由に組み合わせたい時。継承によってごちゃらせたくない時。 |
Composite(容器と中身の同一視) | 部分−全体階層を表現するために、オブジェクトを木構造に組み立てる。Compositeパターンにより、クライアントは、個々のオブジェクトとオブジェクトを合成したものを一様に扱うことができるようになる。 | ディレクトリ内にディレクトリとファイルが存在する、階層の中に更に階層があるような時。 |
Decorator(飾り枠と中身の同一視) | オブジェクトに責任を動的に追加する。Decoratorパターンは、サブクラス化よりも柔軟な機能拡張方法を提供する。 | 柔軟に機能を追加、拡張したい時。 |
Façade(シンプルな窓口) | サブシステム内に存在する複数のインタフェースに1つの統一インタフェースを与える。Façadeパターンはサブシステムの利用を容易にするための高レベルインタフェースを定義する。 | 複数のクラスの呼び出しをまとめたい時。複雑さを軽減したい時。 |
Flyweigh(同じものを共有して無駄をなくす) | 多数の細かいオブジェクトを効率よくサポートするために共有を利用する。 | 文字オブジェクト、タイル等、複数種類のオブジェクトが大量にある時。 |
Proxy(必要になってから作る) | あるオブジェクトへのアクセスを制御するために、そのオブジェクトの代理、または入れ物を提供する。 | オブジェクトの中間的な処理を置きたい時。 |
オブジェクトの振る舞いに関するパターン | ||
Chain of Responsibility(責任のたらい回し) | 1つ以上のオブジェクトに要求を処理する機会を与えることにより、要求を送信するオブジェクトと受信するオブジェクトの結合を避ける。受信する複数のオブジェクトをチェーン状につなぎ、あるオブジェクトがその要求を処理するまで、そのチェーンに沿って要求を渡していく。 | 受信側のオブジェクトを柔軟に追加、変更したい時。結びつきを緩くしたい時。 |
Command(命令をクラスにする) | 要求をオブジェクトとしてカプセル化することによって、異なる要求や、要求からなるキューやログにより、クライアントをパラメータ化する。また、取り消し可能なオペレーションをサポートする。 | コマンド実行をオブジェクトとして切り離したい時。実行したコマンドを管理し、取り消し/再実行を行いたい時。 |
Interpreter(文法規則をクラスで表現する) | 言語に対して、文法表現と、それを使用して文を解釈するインタプリタを一緒に定義する。 | 構文解析を行いたい時。 |
Iterator(1つ1つ数え上げる) | 集約オブジェクトの種類・実装・構造に依存せす、統一的に走査し要素を一個一個取り出す方法を提供する。 | List等の内部表現を公開せずに順にアクセスしたい時。複数の走査オブジェクトに共通のインタフェースを提供したい時。 |
Mediator(相手は相談役1人だけ) | オブジェクト群の相互作用をカプセル化するオブジェクトを定義する。Mediatorパターンは、オブジェクト同士がお互いに明示的に参照しあうことがないようにして、結合度を低めることを促進する。それにより、オブジェクトの相互作用を独立に変えることができるようになる。 | オブジェクト間の通信を仲介させたい時。 |
Memento(状態を保存する) | カプセル化を破壊せずに、オブジェクトの内部状態を捉えて外面化しておき、オブジェクトを後にこの状態に戻すことができるようにする。 | 状態の保存、取り消し/再実行を行いたい時。 |
Observer(状態の変化を通知する) | あるオブジェクトが状態を変えたときに、それに依存するすべてのオブジェクトに自動的にそのことが知らされ、また、それらが更新されるように、オブジェクト間に一対多の依存関係を定義する。 | 状態が変更されたことを複数のオブジェクトに通知したい時。 |
State(状態をクラスとして表現する) | オブジェクトの内部状態が変化したときに、オブジェクトが振る舞いを変えるようにする。クラス内では振る舞いの変化を記述せず、状態を表すオブジェクトを導入することでこれを実現する。 | オブジェクトの複数の状態を明確に分けたい時。 |
Strategy(アルゴリズムをごっそり切り替える) | アルゴリズムの集合を定義し、各アルゴリズムをルール化して、それらを変換可能にする。Strategyパターンを利用することで、アルゴリズムを、それを利用するクライアントからは独立に変更することができるようになる。 | アルゴリズム的な処理を入れ替えたい時。(ソート、テキスト処理等) |
Template Method(具体的な処理をサブクラスに任せる ) | 1つのオペレーションにアルゴリズムのスケルトンを定義しておき、その中のいくつかのステップについては、サブクラスでの定義に任せる事にする。Template Methodパターンでは、アルゴリズムの構造を変えずに、アルゴリズム中のあるステップをサブクラスで定義する。 | 一連の処理の流れが決まっているが、様々なパターンがある時。 |
Visitor(構造を渡り歩きながら仕事する) | あるオブジェクトを構造上の要素で実行されるオペレーションを表現する。Visitorパターンにより、オペレーションを加えるオブジェクトのクラスに変更を加えずに、新しいオペレーションを定義することができるようになる。 | オブジェクトに対するオペレーションを分離して柔軟性を持たせたい時。 |
更にそれぞれのデザインパターンを、「クラス」と「オブジェクト」のどちらに適用するかで分類される。全カテゴリーは正確には6種類に分類されるが大まかには3つの分類でいいとう話も。
目的 | ||||
---|---|---|---|---|
生成 | 構造 | 振る舞い | ||
範囲 | クラス | Factory Method | Adapter | Interpreter / Template |
オブジェクト | Abstract Factory / Builder / Prototype / Singleton | Adapter / Bridge / Composite / Decorator / Façade / Flyweight / Proxy | Chain of Responsibility / Command / Iterator / Mediator / Memento / Observer / State / Strategy / Visitor |
1-3. ソフトウェアパターンの中の一つのカテゴリがデザインパターン
以下のポッドキャストでの対談から引用し、口語体を文章に再構成。
オリジナルのポッドキャストを聞きたい方は以下のリンクからどうぞ。というか全ジュニア絶対聞くべき
プログラミングにおいて、言語・システム・ドメインが異なっても、繰り返し現れる解決策・設計に名前を与えて、暗黙知を形式知にした知識のリポジトリともいうよなもの。
名前を与えることによって知識の共有が可能になった。
そしてその名前がつけられたあるパターンから、
- どういう状況において
- どういう問題を解決しようとしていて
- 問題の構造はどうなっているのか
そのパターンを知っている人には「パターン名」を伝えるだけで、前提が伝わる。ものすごく効率が良い形で、設計意図を相手に伝える為の語彙として使うことができる。
1-4. ソフトウェアパターンには他に何があるのか?
- アーキテクチャパターン
- アンチパターン
- コンカレンシーパターン
- (AWS)クラウドデザインパターン
上記もデザインパターンと同じで、繰り返し現れる解決策に対して名前を与えて、プログラマで知を共有していこうという活動、またはソフトウェア業界でそういったパターンを活用しようという営みのことをソフトウェアパターンと呼んでいる。
1-5. デザインパターンの最小構成
コンテクスト(文脈)
プログラム
ソリューション
どうゆう状況で どうゆう問題が発生して その解決のためのソリューションは何か?
1-6. GoFの歴史
1995年に登場
時代は C++(オブジェクト指向)やSmalltalkやPerl、ちなみにPythonは1991年
2層アーキテキチャ全盛時代で、OSの上のGUIのプラットフォームを使ってGUIのアプリケーションをC++で作る上で出てきた諸問題に対するソリューションとして出てきた。そういった時代背景が土台にあることは理解しておかないといけない。
2. GoFデザインパターンの教え
2-1. 継承ではなく委譲
- 継承はスーパークラスとサブクラス間で非常に強い結合を作る。
- スーパークラスとの実装の結びつきが非常に強い(クラス間での結びつきの管理が必須)
- 継承によるサブクラスの継承階層深化に伴う依存性の強化問題
- 継承は機能を受け継ぐのではなく、交換可能なパーツを作成するために共通点を「規格」としてまとめ上げたインターフェイス
- 車のエンジン・ハンドル・車体・タイヤの様なもの
- 期待される役割が異なる(スーパー)クラスの共通部部分を利用したい際は継承ではなく委譲を用いることで関係のない責務を持たないようしなくてはいけない
- サブクラスにスーパークラスと同じ役割が期待される場合は親と同様に振る舞えるようになる継承を使うのが良い
- サブクラスにスーパークラスと同じ役割が期待されない場合は子にとって親は単なるツール・機能の受け継ぎである可能性が高いため委譲を使うのが良い
2-2. 具象ではなくインターフェイス(抽象)に対してプログラミング
インターフェイスを用いる事で、実装の手続きを画一化し、呼び出す側と呼び出される側の結合度を下げ、実装も隠蔽する。
- 結合度が高くて変更に弱いメソッドの実装詳細と、それを呼び出す側の「間」にインターフェイスを置くことで呼び出し側から実装の詳細が隠蔽され結合が弱まる。
- 達成したい目的(振る舞い)とそれを実現するための機能がメソッドとして定義されているが、具体的にどう実装するかについては制約しない
実装の詳細が変わっても、インターフェイスを呼び出す側には関係がないので、変更の影響箇所を抑える事ができる。
- インターフェイスの呼び出し側では実装の詳細を知らずとも、そのインターフェイスで何が行えるかということだけがわかれば良い
- 実装(手段)の抽象化。実装の詳細はどうあっても構わない。具体的な実装が変わったとしても、インターフェイスそのものが実現する振る舞いが変わらないのであれば呼び出し側には関係がない
- ex.:なんか良く知らんけど、拡張for文(foreach)使えば配列とかコレクションの要素を順番に取ってきてくれるんよね
- インターフェイスの実装は、変更され易い箇所なので保守性の高いコードである事が求められる。変更容易性
- is-a / has-a の様な対象の構造はなんであれ、振る舞い・責務についてプログラミングする
これにより、ポリモーフィズムを使用したプログラミングができる様になる。結果、デザインパターンを利用する側のコードを再利用できる様になった。
2-3. オブジェクト指向プログラミングでの本質的な再利用性の提示
- 多段階継承の様な差分プログラミングの実装の再利用ではなく、ポリモーフィズムを使うことによる利用側のコードの再利用である
- 誤解された継承のように、差分プログラミング(DRY)を実現するのはスーパークラスを継承することのみではない
- 差分を抽出する方法は継承のみではなく、別のクラスの抽出することも選択肢としても見るべき
- 参考:Strategy(アルゴリズムをごっそり切り替える)
2-4. 「変更されない部分」と「変更される部分」の分離
- 変更されない箇所を軸に頻繁に変更されるであろう箇所をクラスに抽出する
- 変更される側は、変更に強い構造にできる。その構造とはなんですか? = GoFデザインパターン
- 変更されない部分は再利用ができる(デザインパターンに対してのコード)
※ Golang / Rust にはそもそも継承がない
3. 1995年登場時のGoFデザインパターンの立ち位置【リファクタリングと自動テストがなかった時代】
設計によって変更に強いシステムを開発する上で、変更に強い構造の見本としてのデザインパターン
設計によって変更に強くなるソフトウエアが作れるという空気感の時代だった。システムを分析すれば、変更のされやすい / されづらい部分で切り分けられる。変更に強い構造はGoFデザインパターン。
しかし、その後設計者・開発者の間で「変更されやすいところ」を本当に把握できているのか?と思わされる様な事態が多く起きた。事前に設計段階で用意していたものが、うまく使用される事が少なかった。想像を超えた変更が多く、設計段階で変化に強いシステムにできるというのは机上の空論だった。想像を超える多くの変化がはいってくるが、その変化の一つ一つは生きた変化であった。実際のユーザからの生きたニーズによる変化。
設計によって備えるというのが、実際の生きた変化にどのくらいフィットできるのかというのが疑問に思われたのが2000年代前半の空気感。自分達が思ったよりも、将来を予期した設計はできない。自分達で備えても大体においてその通りにはならないし、準備した備えは使う事がなかった。では、備え方を変えようという考えに変化した。今必要ないなら、将来においても必要ないという思考にシフトチェンジされていったのである(YAGNI)。
4. GoFデザインパターンの立ち位置【リファクタリングと自動テストが登場してから】
リファクタリングに方向性・ターゲット・語彙を与えるためのより良いサンプルとしてのデザインパターン
リファクタリングと自動テストが登場し設計を後から安全に変更できる様になり、後から現実にシステムを合わせる事ができる様になった。これにより、設計に重きを置きすぎて硬直する事を回避する事ができる様になる。変更に強い設計はもちろん大事だけど後から直すことも重要視されるようになった。
新たな生きたニーズが入ってきたら、それに合わせた設計にする。既存との設計の差異・似ている部分をリファクタリングしながらデザインパターンに近づければ良いじゃないかという考えに変わった。最初からパターンを設計するものではなくて、リファクタリングの結果生まれてくるものがデザインパターンに変わっていった。
備え、という認識も変化。変化に対して構造で備えるのではなく、備えない事・身軽でいる事が備えになった。 将来は何が起きるかわからないし、想像を超えた仕様変更がやってくる。現状の仕様を実現するコードを最もシンプルに設計・実装し、新たな仕様にもシンプルに対応するといった考えに変わった。その中で、似通った構造・パターンが出てくるからリファクタリングによって、保守性の高い構造にしていき、その保守性の高い構造のサンプルがGoFのデザインパターンだった。
この様な流れでGoFデザインパターンの立ち位置は、「変更に強い構造の設計を行うための見本」から「リファクタリングの方向性としての見本」に変化していった様です。
また現代においては、GoFデザインパターンそのものよりリファクタリングの方が重要になっているとのことです。
詳細な話については上記でも紹介しているポッドキャストの後半編をお聞きください。めちゃくちゃ勉強になります。
5. 15年後の2009年に行われた GoFによるGoFデザインパターンの再定義(重要)
15 年後に再整理された Design Patterns / Erich Gamma、Richard Helm、Ralph Johnson へのインタビュー
- カテゴリの変更
- Core:最も使用される重要なパターン
- Creational:生成に関するパターン
- Peripheral:あまり使わない
- Other:その他
- 変更(1):Factory Method は Factory に一般化
- 新規追加(4):Null Object, Type Object, Dependency Injection, Extension Object/Interface
- 削除(6):Singleton, Adapter, Bridge, Chain of Responsibility, Memento, Observer
- 格下げ:Flyweight, Interpreter
- Core: Composite, Strategy, State, Command, Iterator, Proxy, Template Method, Facade
- Creational: Factory, Prototype, Builder, Dependency Injection
- Peripheral:Abstract Factory, Visitor, Decorator, Mediator, Type Object, Null Object, Extension Object/Interface
- Other:Flyweight, Interpreter
5-1. 新規追加パターンについて
- Null Object(存在と不在の同一視)
- Nullの場合の振る舞い・Nullでなかった場合の振る舞いを持たせる。ポリモーフィズムの延長、Composite(全体と部分の同一視)の亜種。
- Type Object
- 型を動的に作成。どんな型が必要なるか前もってわからない場合に使用。
- Dependency Injection
- 依存性オブジェクトの注入。クラスが依存するオブジェクトの生成方法を隠蔽して提供する。
- Extension Object/Interface
- プラグアブルな拡張のパターン。eclipseで使用されている。
5-1-1 これまでの分類表
目的 | ||||
---|---|---|---|---|
生成 | 構造 | 振る舞い | ||
範囲 | クラス | Factory Method | Adapter | Interpreter / Template |
オブジェクト | Abstract Factory / Builder / Prototype / Singleton | Adapter / Bridge / Composite / Decorator / Façade / Flyweight / Proxy | Chain of Responsibility / Command / Iterator / Mediator / Memento / Observer / State / Strategy / Visitor |
5-1-2. 2009年以降の分類表
Core | Creational | Periphenal | Other |
---|---|---|---|
Composite / Strategy / State / Command / Iterator / Proxy / Template Method / Facade | Factory / Prototype / Builder / Dependency Injection | Abstract Factory / Visitor / Decorator / Mediator / Type Object / Null Object / Extension Object/Interface | Flyweight / Interpreter |
5-2. 現在においてもデザインパターンは有用か?
上記の話からもおわかりの通り有用ですよね。ただ、以下の様な批判・意見も存在します。
引用:Wiki
一部のデザインパターンは、プログラミング言語(例: Java, C++)の機能の欠損の印であると主張されることがある。計算機科学者のピーター・ノーヴィグは、GoFによるデザインパターン本の23パターンのうち16パターンは、言語によるサポートによって単純化または除去できることをLispやDylanを用いて実演した
登場から20年以上たって、コンテキストも大きく変わり言語の進化や価値観の変化が起きている。当然、現代においてのコンテキスト・プログラム・ソリューションに当時のパターンがそのままフィットしないものだってある。
また、すでに言語に標準で搭載されているものもあるようで、有用か有用じゃないかの観点より実装する必要があるかないか?といった観点も出てくる。だからといって必要なくなるわけでは決してない。
オブジェクト指向の3大要素である「継承」「カプセル化」「ポルモーフィズム」を理解するためには必ず必要な知識ではないしょうか?他、抽象クラス・interfaceがなぜ必要なのか?具体的なクラスだけの実装でなんの問題が有るのか?そういった問にも答えを出してくれます。クラス志向オブジェクト言語においてよりよい設計・コード実装に必要な知識がデザインパターンには含まれると考えます。
→ 実際にやってみてめっちゃ含まれてました。
私はいろんな職種で働いて、いろんな勉強をしてきました。昔から語り継がれるもので役に立たなかったことって全く無いんですよね。
今は当然になった仕組みも、当時の問題課題を解決するために登場したものであって、そのソリューションがまた新たな問題課題を生み出しそれに対するソリューションを作り出していく。この繰り返しの上に現在があるので、現在当たり前の仕組みであってもそれを真に理解するには登場時の背景まで理解する必要が有ると思います。
6. UMLについて
基礎知識・用語集
6-1. クラス図
①階層関係のextends
サブクラスからスーパークラスへ伸びる白抜き矢印。矢印の向きが逆ではない理由
②記述の順番
- クラス名
- フィールド名
- メソッド名
その他の記載事項
- アクセス制御
- 引数・型
③abstractクラス・メソッド
- 斜字体
④staticフィールド・メソッド
- 下線
⑤interfaceのimplements
- Javaでのインターフェースは<< interface >>と記述
- 白抜き破線矢印
⑥集約
- 白抜きひし形矢印
⑦アクセス制御
- + → public(何処からでもアクセス可能)
- - → private(クラス内のみアクセス許可)
- # → protected(同じクラス・サブクラス、同じパッケージ内のクラスのみアクセス許可)
- ~ → アクセス修飾子を記述しない(同じパッケージ内のみアクセス可能)
6-2. クラスの関連
6-3. シーケンス図
プログラムが動く時にどのメソッドがどういう順番で実行され、どの様な事象がどういう順番で起きるか、どいうった流れで処理が進むかなどを表現。 関連する複数のインスタンスの振る舞いを図式化したもの。
クラス図は「時間によって変化しない(静的)」に対して、シーケンス図は「時間に従って変化するもの(動的に振る舞う)」
下方向に伸びる破線をライフライン(生存線)と呼ぶ。時間軸は 上は過去、下は未来。 ライフラインは、インスタンスが存在する間だけ存在。 ライフラインをたどりながら上から順番に読み、矢印を追ってインスタンス間の協調動作を確認する。
要素 | 表示形式 | 意味 | |
ライフライン(Lifeline) | コロン(:) の後にクラス名が書かれ、下線。それぞれClientクラス・Serverクラス・ Device クラスのインスタンスを表す。 | ||
実行仕様(ExecutionSpecification) | 生成されたオブジェクトが活動中であることを示す | ||
停止(Stop) | 生成されたライフライン自体の消滅を意味します。 | ||
メッセージ(Message) | 同期(Synchronous)メッセージ | メソッドの呼び出しを表す。 ここでは、client が serverのopenメソッドを呼び出したことを表す。 | |
応答(Reply)メッセージ | メソッドからのリターン (戻り) を表す。 | ||
ファウンド(Found)メッセージ | 図解上にない送り手から送られた、もしくは送り手がダイアグラム上にないことを意味。 | ||
ロスト(Lost)メッセージ | 意図された受け手に送られていない、もしくは受け手がダイアグラム上にないことを意味。 |
6-3-1. クラス、インスタンス、オブジェクトの違い
「Aさんというオブジェクトは人間というクラスのインスタンスである」
インスタンスとは、クラスを元に作り出したオブジェクトのこと。
- インスタンスはオブジェクトである
といえるが、
- オブジェクトはインスタンスである
とは言えない。
プログラミング言語によって、クラス以外からできるオブジェクトが存在しているため。
7. プログラムを完成品としてみない
デザインパターンの目標の1つは、プログラムを再利用可能にすることです。 つまり、 どうやってプログラムを 「部品」として再利用するかを考えているのです。 ですから、プ ログラム例を「完成品」として見るのではなく、今後「機能を拡張していくもの」 「変更 を加えていくもの」 として見るようにしましょう。
- どのような機能が拡張される可能性があるか?
- その機能拡張を行うときに修正が必要になるのはどのクラスか?
- 修正が必要なのはどのクラスか?
この様な観点でデザインパターンを見ると、理解が深まるでしょう。
これから、一つ一つデザインパターンを学んでいきます。楽しみです。