1.6 代表的デザインパターンの利点(MVC, Observer)
デザインパターンとは、よく出会う設計上の問題に対する「名前のついた定番の解き方」である。本ページでは、まず「定石に名前がつくこと」がなぜ役立つのかを押さえ、代表例として MVC と Observer が、それぞれどんな困りごとを解くのかを見ていく。
なぜ「名前のついた定石」が役立つのか
デザインパターンが役立つのは、先人が繰り返しぶつかった問題と、その良い解き方を、名前つきの再利用できる知恵としてまとめてあるからである。ゼロから悩まずに済むうえ、名前が共通の語彙になる。
ソフトウェアを設計していると、「機能と見た目を分けたい」「あるものの変化を複数の相手に知らせたい」といった、似た構造の問題に何度も出会う。多くの開発者が同じ壁にぶつかり、それぞれに「うまくいく形」が経験的に固まってきた。それを整理し、名前をつけたものがデザインパターンだ。
名前がつくことには、解き方を再利用できること以上の効果がある。「ここは MVC で分けよう」「この通知は Observer で」と一言で意図が伝わる。設計の会話が速くなり、コードを読む人も構造を予測しやすくなる。料理の「定番レシピ」に名前があるおかげで、毎回ゼロから考えず、人にも一言で伝えられるのと同じだ。
Note
デザインパターンは「当てはめれば良くなる魔法」ではない。問題の形に合っていないのに無理にパターンを適用すると、かえって複雑になる。パターンは「この問題にはこの形が効きやすい」という知恵であって、使うこと自体が目的ではない。まず解きたい問題があり、それに合うときに選ぶものだ。
MVC ―― なぜ関心の分離につながるのか
MVC は、アプリを Model・View・Controller の3つの役割に分けるパターンである。これにより「データの扱い」「見た目」「操作の仲介」という別々の関心事が混ざらず、独立して変更できるようになる。
- Model(モデル) — データそのものと、それを扱うルール(業務ロジック)を担う。たとえば機器の一覧や状態、その計算がここに入る。見た目のことは知らない。
- View(ビュー) — 利用者に見せる表示を担う。同じデータを表で見せるか、グラフで見せるかはここの仕事だ。データの中身の計算はしない。
- Controller(コントローラ) — 利用者の操作を受け取り、Model に指示を出し、結果を View に渡す仲介役。両者をつなぐ交通整理を担う。
flowchart LR
U["利用者"] --> C["Controller
操作を受けて仲介"]
C --> M["Model
データと処理"]
M --> V["View
表示"]
V --> U分離しないと何が困るのか。表示のコードとデータ処理のコードが混ざっていると、「見た目だけ変えたい」のにデータ処理に触れてしまい、思わぬ不具合を生む。「同じデータを別の画面でも見せたい」とき、表示と処理が一体だとデータ処理ごとコピーするはめになる。役割を分けておけば、View を差し替えても Model は無傷で、Model の計算を直しても View は影響を受けない。これが 関心の分離——異なる種類の事柄を別々の場所に置き、互いに独立させること——の利点である。1.5 の「変更の局所化」を、役割という軸で実現したものと捉えるとよい。
MVC が向くのは、同じデータに複数の見せ方があったり、表示と処理がそれぞれ独立に変わっていく、Web アプリや管理画面のようなものだ。
Observer ―― 変化の通知を解く
Observer(オブザーバ=観測者)は、「あるものの状態が変わったとき、それを気にしている複数の相手へ自動で知らせる」というパターンである。知らせる側が相手を1つずつ呼びに行く代わりに、相手のほうが「変化したら教えて」と登録しておく。
flowchart TD
S["観測対象
状態が変わるもの"] -->|変化を通知| O1["観測者1"]
S -->|変化を通知| O2["観測者2"]
S -->|変化を通知| O3["観測者3"]このパターンが解く問題を、観測対象なしの世界で考えると分かりやすい。もし通知の仕組みがなければ、知りたい側は「変わったかな?」と何度も自分から問い合わせ続ける(ポーリングという)しかない。ムダが多く、変化を知るのも遅れる。さらに、知らせる側が相手を直に呼び出す作りにすると、相手が増えるたびに知らせる側のコードを書き換えることになり、両者が固く結びついてしまう。
Observer はここを切り離す。観測対象は「変化した」と一斉に通知するだけで、誰が聞いているかを個別に知る必要がない。観測者は好きなタイミングで登録・解除できる。両者の結びつきが緩むので、通知を受ける相手を後から自由に足し引きできる。
ネットワークの文脈と相性がよいのはこの性質ゆえだ。たとえば監視システムで「あるインターフェースがダウンした」という変化を、ログ記録・管理者への通知・自動復旧スクリプトといった複数の相手へ同時に伝えたい場面。観測対象(インターフェースの状態)が変化を1回通知すれば、登録済みの各処理がそれぞれ反応する。受け手を増やしても、観測対象側は変えなくてよい。イベント処理(何かが起きたことを起点に動く仕組み)全般に、この考え方が広く使われている。
どんな場面で何を選ぶか
2つは解く問題が別物なので、迷ったら「何を分けたいか」で選ぶ。役割(データ・表示・操作)を分けて独立に変更したいなら MVC。状態の変化を複数の相手に知らせたいなら Observer。実際のシステムでは、MVC で全体の役割を分けつつ、その中の通知に Observer を使う、というように複数のパターンが組み合わさることも多い。パターンは排他的な選択肢ではなく、問題ごとに使い分け・組み合わせる道具箱だと捉えるのがよい。
本ページはCisco DevNet Associate(200-901) Exam Topics v1.1を学習範囲の根拠として参照。文章・図表はすべて新規作成。