情報システム開発の設問で図が出てきたとき、読むべきものはほぼ2つです。線の先端に付いた記号(どういう関係か)と線の両端に書かれた数字(多重度=いくつ結び付くか)。この2つを取り違えると、空欄の答えがまるごと変わります。逆に言えば、記号と多重度さえ正確に読めれば、クラス図の設問は大半が機械的に片づきます。
オブジェクト指向は「データ(属性)とそれを扱う手続き(操作)を1つのまとまりにする」考え方で、そのまとまりの設計図がクラス、実際に動く実体がオブジェクト(インスタンス)です。UMLはその設計を描くための共通の記法。クラス図=静的な構造(誰と誰が、いくつ、どう関係するか)、シーケンス図=動的なふるまい(誰が誰を、どの順で呼ぶか)。何を見せたいかで図が分かれているだけです。
クラス図の読み方
クラスは3段の箱で描きます。上からクラス名/属性/操作。属性はそのクラスが持つデータ、操作はそのクラスができることです。箱と箱をつなぐ線が関連で、線の端に多重度を書きます。
クラスの箱と関連(1人の会員が0個以上の注文を持つ)
氏名
住所
注文履歴を返す()
関連(持つ)
注文日
合計金額
取り消す()
この図は「会員1人に対して注文は0個以上」「注文1件に対して会員はちょうど1人」と読みます。多重度は相手側の端に書かれた数を読むのが原則で、自分の側の数字ではありません。ここを逆に読むと全問ずれます。
記号の意味を図で区別する
試験で問われるのは、ほぼこの3つの記号です。線のどちら側に付いているか(全体側か部分側か、親側か子側か)まで含めて覚えます。
「〜は〜の一種である」の関係。三角は親(一般的なほう)側に付く。子は親の属性・操作を受け継ぐ。
例:正社員/派遣社員 は 従業員 の一種
「全体と部分」だが、部分は全体が消えても単独で存在できる。ひし形は全体側に付く。
例:チームと社員(チーム解散でも社員は残る)
集約より強い全体と部分。全体が消えると部分も消える(生存期間を共にする)。ひし形は全体側。
例:注文と注文明細(注文が消えれば明細も消える)
白と黒のひし形を「なんとなく強さの違い」で済ませると選択肢で迷います。判断は「全体を消したとき、部分は生き残るか」の一点。生き残る=白ひし形(集約)、道連れで消える=黒ひし形(コンポジション)。そしてひし形は必ず全体側、三角は必ず親側。記号の付く向きが逆の選択肢は、それだけで切れます。
汎化(△は親側)とコンポジション(◆は全体側)
所属
汎化(〜の一種)
コンポジション(消えたら道連れ)
多重度の読み方
| 表記 | 意味 | 読みどころ |
|---|---|---|
1 | ちょうど1つ | 必ず1つ結び付く。0も2つ以上も許さない |
0..1 | 0か1つ | 「あってもなくてもよい」=省略できる関係 |
0..* | 0以上(いくつでも) | 1つも無くてよい。空の状態が正常として存在する |
1..* | 1以上(最低1つ必要) | 0は許されない。必ず1つ以上ぶら下がる |
* | 0..*と同じ | 下限が書かれていなければ0が許される |
解答が割れるのは0..* と 1..* の差です。問題文には必ず根拠が書いてあります。「明細を1件以上含む」「少なくとも1つ登録する」なら 1..*。「まだ注文していない会員も登録できる」「0件の場合もある」なら 0..*。本文の「〜がない場合もある」「必ず〜を持つ」という一文が、そのまま下限0か1かを決めています。図を眺めて決めるのではなく、本文の一文を根拠に引くのが正解への最短路です。
オブジェクト指向の4本柱
カプセル化
- データと操作を1つに包む
- 属性は直接いじらせず操作経由
- 効果:内部を変えても外に波及しない
継承
- 親の属性・操作を受け継ぐ
- 共通部分を親に1か所だけ置く
- 効果:重複が消える/修正が1か所
ポリモーフィズム
- 同じ呼び方で相手ごとに違う動き
- 呼ぶ側は相手の種類を知らなくてよい
- 効果:種類を増やしても呼ぶ側は無修正
抽象化
- 本質だけ残して細部を隠す
- 抽象クラス:共通処理は書き、個別処理は「あとで各自が書く」と宣言だけする
- インタフェース:呼び口(操作の名前と引数)だけを決め、中身は一切持たない
「共通の呼び口」の役割
- 抽象クラス/インタフェースは約束事
- 呼ぶ側は約束だけ見て呼ぶ
- 実装が10種類に増えても呼ぶ側のコードは変わらない
4本柱はバラバラの用語ではなく、「変更に強くする」ための一本の筋です。カプセル化で影響範囲を閉じ、抽象化で呼び口を固定し、継承で共通部分を1か所に集め、ポリモーフィズムで種類の追加を呼ぶ側から隠す。設問でこれらの効果を問われたら、答えは大体「変更・追加のときに直す箇所が減る」方向です。
シーケンス図の読み方
クラス図が「誰と誰が関係するか」なのに対し、シーケンス図は「誰が誰を、どの順で呼ぶか」を描きます。時間軸は縦(上から下へ)、メッセージは横向きの矢印。上に並んだ箱がオブジェクトで、そこから下に伸びる縦の点線が生存線です。
↓ 時間は上から下へ/横矢印=メッセージ(操作の呼び出し)
実線の矢印が呼び出し、破線の矢印が戻り。生存線の上に細長く重なる長方形は実行仕様(そのオブジェクトが処理中である期間)を表します。空欄補充で問われるのは「この位置の矢印は誰から誰へ、どの操作か」で、根拠はクラス図でその操作を持っているのは誰かにあります。2つの図を行き来して答えるのが定石です。
デザインパターンの例:Observer
デザインパターンは、よく出る設計の型に名前を付けたものです。代表格のObserver(オブザーバ)は「状態が変わったら、登録済みの相手にまとめて通知する」型。通知する側(被験者)と通知される側(観察者)をインタフェースで切り離すのが要点です。
Observer:通知する側は「観察者」という呼び口しか知らない
解除する(観察者)
変更を通知する()
通知先として保持
実現(破線+白抜き三角)
この呼び口を備える
インタフェースと実装クラスを結ぶ実現は、破線+白抜き三角で描きます。実線+白抜き三角の汎化とは線の種類で区別する——三角が同じなので、線が実線か破線かを見落とすと汎化と取り違えます(クラスを継いだのか、呼び口だけを備えたのか)。
在庫データが持っているのは「観察者」という呼び口のリストだけで、相手が一覧画面なのかグラフなのかは知りません。だから通知される側を後から増やしても、在庫データ側は1行も直さなくてよい——これがこのパターンの利点であり、設問で問われる効果そのものです。多重度が 0..* なのは、誰も登録していない状態も正常だから。ここも本文の根拠と対応します。
設問での急所
クラス構成を答える問題の判断軸は「共通処理は抽象側、個別処理は具象側」です。複数のクラスに同じ処理が重複して書かれていたら親(抽象クラス)へ引き上げる、逆に種類ごとに中身が違う処理は抽象側では名前だけ宣言し、具象側で実装する。この配置にしておくと、種類を1つ追加しても新しい子クラスを足すだけで済み、既存のコードを触らずにすみます。「拡張しやすい設計はどれか」「変更の影響を小さくするにはどう直すか」と問われたら、ほぼこの形が答えです。
もう一つの失点源が多重度の下限。0..* と 1..* は図の見た目がほぼ同じなのに、意味は「無くてよい/必ず要る」で正反対です。答案を書く前に、必ず問題文へ戻って「0件のケースが本文に書かれているか」を確認してください。書かれていれば 0..*、「必ず1つ以上」「少なくとも1件」とあれば 1..*。ここだけで配点が動きます。