本連載の目的は、「UMLのフルスペックをいかに使いこなすか」ではなく、「Java開発をターゲットにしたUMLの使い方」を明確にする点にあります。そして、Javaをターゲットにした設計モデルを作成するために必要なUMLのプロファイルを提案することが最終的な目標となります。
この目的には、メタモデルを起点としたトップダウンのアプローチではなく、ノーテーションを起点としたボトムアップのアプローチが有効です。もちろん、これはUML利用者の立場から見たUMLがノーテーションであることによります。
以上の点から、本連載では「第7回 静的モデル:リレーションシップ(1)」で解説した「UMLノーテーションから見たリレーションシップ」のモデルをベースに議論を進めていくことにします。
本連載で用いるリレーションシップの全体像を再度振り返っておきましょう(図1)。
リレーションシップは大きく、アソシエーション、汎化、リアライゼーションに分けることができます。また、以上のいずれにも属さないリレーションシップがディペンデンシィとなります。アソシエーションは、集約と集約以外のアソシエーション、さらに、集約は合成集約と合成集約以外のアソシエーションに分けられます。
アソシエーションの重要な部分集合には、集約があります。アソシエーションは大きく分けて以下の3つに分類することができます。
・(集約でない)アソシエーション
・(合成集約でない)集約
・合成集約
アソシエーションには集約と集約でないアソシエーションの2種類のアソシエーションがあります。また、集約には合成集約と合成集約でない集約の2種類の集約があります。このため、厳密には単にアソシエーションといった場合、集約でない普通のアソシエーションなのか、集約なのかの区別はつきません。また、集約にも合成集約との間に同様のあいまいさが存在します。そこで本連載では、アソシエーションを「集約でないアソシエーション」、集約を「合成集約でない集約」の意味で用いることにします。
リアライゼーションは前述したようにメタモデル上はDependencyの一種であるAbstractionに対してステレオタイプrealizeを指定したモデル要素となっています。分かりやすくいうとリアライゼーションはディペンデンシィの一種ということになります。しかし、この定義通りの用語法を用いると繁雑になってしまうので本連載では、ディペンデンシィを「リアライゼーションでないディペンデンシィ」の意味で用いることにします。
前節では、リレーションシップの「本連載内での定義」を再確認しました。それでは以下、本連載で用いる各リレーションシップの機能について簡単に説明しておきます。イメージをつかんでいただくために、簡単なUMLとJavaのマッピングにも触れておきます。図の中に登場する細かな修飾については今回は説明しませんが、次回以降各リレーションシップの説明の中で詳しく取り上げる予定です。
アソシエーション(association、関連)は、分類子のインスタンスの間にコネクションがあるというリレーションシップです。アソシエーションの使用例を図2に示します。OrderHandlerのオペレーションが、パラメータという形でOrderとのコネクションを持つというリレーションシップを示しています。
リスト1に、このUML図に対応するJavaソースの例を示します。receiveOrderメソッドの引数としてOrderが参照されています。
public class OrderHandler { public void receiveOrder(Order order) { recordOrder(order); delivery(order); } public void recordOrder(Order order) { ... } public void delivery(Order order) { ... } }
集約(aggregation)は、クラスが別のクラスの一部であることを表すアソシエーションです。集約の使用例を図2に示します。OrderItemはProductを構成要素として持っています。ただし、OrderItemが消失しても、これと同期してProductは消失しないという関係を示しています。
このUML図をJavaにマップしたものがリスト2です。この例でも分かる通り、集約は通常Javaの属性として実装されます。
public class OrderItem { public Product product; }
合成集約(composition、composite aggregation)は、クラスが別のクラスの完全な一部になっていることを表す集約です。合成集約の使用例を図4に示します。Orderは複数のOrderItemと合成集約の関係を持っています。つまり、Orderが消失すれば同時にOrderItemも消失するという強い依存関係を持っているわけです。
1つのOrderが複数のOrderItemを持っているという関係を実装するために配列を用いています。このUML図をJavaにマップしたものがリスト3です。
public class Order { public OrderItem[] items; }
Javaでの実装では、合成集約から導かれる「Orderが消失すると同時にOrderItemも消失する」という部分を実装に反映することはかなり難しくなってしまいます。このあたりが、UMLからJavaへのマッピングで苦労しそうなところとなるわけです。
汎化(generalization)は、より汎用的なモデル要素とより特殊な要素の間にあるリレーションシップです。いわゆる継承(インヘリタンス)と呼ばれているものです。ただし、継承と汎化は厳密には意味が異なります。汎化の使用例を図5に示します。より汎用的なクラスであるAbstractionOrderReceiverと、このAbstractionOrderReceiverの特殊化したクラスであるWebOrderReceiverの間に汎化の関係があることを示しています。
このUML図をJavaにマップしたものがリスト4です。UMLの汎化はJavaではextendsによって表現されます。
public class WebOrderReceiver extends AbstractOrderReceiver { }
リアライゼーション(realization、実現)は、仕様のモデル要素とその実装のモデル要素の間にあるディペンデンシィです。リアライゼーションの使用例を図6に示します。クラスAbstractionOrderReceiverがインターフェイスIOrderReceiverを実現する関係にあることを示しています。
このUML図をJavaにマップしたものがリスト5です。クラスがインターフェイスをリアライゼーションする関係はJavaではimplementsで表現されます。
public abstract class AbstractOrderReceiver implements IOrderReceiver { }
このとき、IOrderReceiverはリスト6のようなJava interfaceとして実現されます。
public interface IOrderReceiver { }
ディペンデンシィ(dependency)は、アソシエーション、汎化、Flow、メタ関係以外のあらゆるリレーションシップを総称した用語です。ただし、前述した通り、本連載のディペンデンシィは、さらにリアライゼーションを除外したものになります。ディペンデンシィの使用例を図7に示します。AbstractOrderHander内のオペレーションがOrderHandler内のオペレーションを呼び出す、という関係を示しています。
このUML図が表現するJavaプログラムの例がリスト7です。
public class AbstractOrderReceiver { private OrderHandler handler; public void receiveOrder(Order order) { handler.handleOrder(order); } }
最後に、今回登場したリレーションシップを使ったクラス図の例を図8に示します。
このような形で、リレーションシップを駆使してクラスやインターフェイスの関係を明らかにしていくことが静的モデルの主眼となります。
今回は、分類子と並んで静的モデルの核となるモデル要素であるリレーションシップについて概観しました。リレーションシップそのものは抽象的な概念ですから、Javaとの直接の関係は出てきません。リレーションシップを具象化したモデル要素であるアソシエーション、汎化、ディペンデンシィがJavaとの対応関係を持ってきます。
次回から、アソシエーション、集約、合成集約、汎化、リアライゼーション、ディペンデンシィの順番でJavaによる実装を考えていきます。
Copyright © ITmedia, Inc. All Rights Reserved.