第14回 静的モデル:Javaを前提としたUMLアソシエーションJavaオブジェクトモデリング

» 2003年10月29日 12時00分 公開
[浅海 智晴 ,@IT]

 前回「第13回 静的モデル:アソシエーションのJavaの部品」はUMLの観点からの部品、Javaの観点からの部品について確認をしてきました。今回は、これらの部品を組み合わせて、Javaプログラムを前提としたUMLアソシエーションのプロファイルについて考えていきます。UMLアソシエーションのプロファイルに関する全体の構成は以下のようになります。

4.1 方針

4.2 変数のマッピング

4.3 必須の部品

4.4 集約

4.5 多重度

4.6 順序付け

4.7 変更可能性

4.8 限定子

4.9 インターフェイス指定子

4.10 配列

4.11 Collection

4.12 List

4.13 Set

4.14 SortedSet

4.15 Map

4.16 SortedMap

4.17 プロファイルのまとめ

 今回は「4.5 多重度」までを解説します。

4 プロファイル

■■4.1 方針■■

 アソシエーションは、アソシエーション本体とアソシエーション・エンドから構成されます。

●4.1.1 アソシエーション本体

 結論からいうと、アソシエーション本体については、特にプロファイルで必要とする部品はありません。以下にアソシエーション本体を構成する部品をプロファイルでは積極的に使用しない理由を示します。

<<アソシエーション名>>

 UMLとJavaのマッピングのところで説明したとおり、アソシエーション名そのものはJavaプログラム側では利用されません。このため、プロファイルではアソシエーション名の利用方法について、特に定義しないことにします。必要に応じて参考情報として利用すればよいでしょう。

<<ステレオタイプimplicit>>

 ステレオタイプimplicitは暗黙のアソシエーションが存在するという意味なので、当然Javaとのマッピングには関係してきません。必要に応じて参考情報として利用すればよいでしょう。

<<制約xor>>

 制約xorは、設計の段階ではあまり利用されることはありません。また、利用されることがあっても実装方法は利用目的によって変わってきてしまいます。このためプロファイルでは特に使い方を定めません。必要に応じて参考情報として利用すればよいでしょう。

<<タグ付き値persistence>>

 タグ付き値persistenceは、アソシエーションが永続化される、簡単にいうとデータベースに格納されるということを意味しています。当然Javaの基本機能ではカバーしていない機能であり、実装方法は利用目的とターゲットとなるデータベースによって大きく変わってきます。このためプロファイルでは特に使い方を定めません。必要に応じて参考情報として利用すればよいでしょう。

●4.1.2 アソシエーション・エンド

 アソシエーション本体には、Javaとのマッピングで活用できる情報はありませんでした。それに対して、アソシエーション・エンドは重要な情報をたくさん持っています。本プロファイルでは、アソシエーション・エンドの部品として、必須の部品と追加情報の部品を用意します。

■■4.2 変数のマッピング■■

 それでは、JavaからUMLにマップする場合はどうなるでしょうか。表1は、Javaのインスタンス変数/クラス変数のマッピングルールです。

Java UML
プリミティブ型 属性
参照型 バリューオブジェクト 属性
普通のオブジェクト アソシエーション
表1 変数のマッピング

■■4.3 必須の部品■■

 アソシエーション・エンドでは、以下の部品を必須部品とします。

  • ロール名
  • 誘導可能性
  • 可視性
  • ターゲット・スコープ

●4.3.1 UMLでの表現

 図1はプロファイルにおける必須形式です。上側の図が基本型、下側の図が省略形です。正確さという意味では基本型が望ましいですが、実務的な観点から省略形を用意しておくと、より簡単に使うことができます。

ALT 図1 プロファイル必須形式
  • ロール名があるアソシエーション・エンドには誘導可能性があると仮定
  • 可視性はprivateと仮定

 ターゲット・スコープがオブジェクトの場合、UMLの表現では、何も追加の指定がないので、意識する必要はありません。デフォルト値の場合は表示を省略できるという扱いになっています。ロール名はデフォルト値がないので、指定が必須になります。

●4.3.2 Javaでの実装

 図1で示した必須項目が指定されたアソシエーションのJavaでの実装は以下のようになります。

public class Company {
    private Person employee;
}
リスト1 必須の形式

 誘導可能性が変数を保持するクラスを特定します。ターゲット・スコープがインスタンス変数とクラス変数の切り分けに、ロール名がインスタンス変数名に、可視性がJavaの可視性にマップされています。

■■4.4 集約■■

 集約はUMLの通常の使い方と同じです。

●4.4.1 UMLでの表現

 集約の表現は、図2に示すとおり集約指示子を使用します。図の左側が集約、図の右側が合成集約です。集約の表現に省略形はありません。集約指示子を省略すると、集約ではないアソシエーションであることを示します。

ALT 図2 プロファイル/集約(クリックすれば拡大

●4.4.2 Javaでの実装

 Javaでは、通常のアソシエーション、集約、合成集約のいずれも以下に示すようにインスタンス変数を用いた実装になります。アソシエーション、集約、合成集約の違いを直接表現するための機能をJavaは持っていないため、この点を忠実にマップするためには、Javaプログラム内で相応の作り込みが必要となります。

import java.util.Collection;
import java.util.ArrayList;
public class Company {
    private Person employee;
}
リスト2 集約

 プロファイルでは、アソシエーション、集約、合成集約の機能を忠実に実現するための作り込みについては特に規定しません。つまり、UML 上のモデルでアソシエーション、集約、合成集約を正確に使い分けても、Javaへのマッピングでは無視されるということになるわけです。もちろん、これは「アソシエーション、集約、合成集約の使い分けがモデル上重要でない」ということをいっているわけではありません。

■■4.5 多重度■■

 多重度はUMLの通常の使い方と同じです。

●4.5.1 UMLでの表現

 多重度の表現は、図3に示すとおりUMLの通常の指定方法となります。

ALT 図3 プロファイル/多重度(クリックで拡大

 図3では、以下のパターンを記述しています。Javaへのマッピングを考える場合、これらのパターンでの対応が決まっていれば十分です。

  • 必ず1つ存在
  • 1つ存在するかしないか
  • 1以上任意の個数存在
  • 0以上任意の個数存在
  • 固定個数存在
  • 可変個数存在

 また、Javaでの実装との連携を目的として以下の独自タグ付き値を導入します。

  • collectionType
  • collectionClass

 タグ付き値collectionTypeは、多重度を実現する際のインスタンス変数の型を指定します。タグ付き値collectionClassは、多重度を実現する際の実装クラスを指定します。タグ付き値collectionClassで指定されるクラスは、タグ付き値collectionTypeで指定される型として有効でなくてはなりません。以上のタグ付き値を使用したアソシエーションは 図4となります。

ALT 図4 プロファイル/多重度/独自タグ付き値(クリックすれば拡大

●4.5.2 Javaでの実装(1)

 UMLの多重度とJavaでの実装の関係は表2となります。表から分かるとおり、Javaでの実装には以下の3つしか選択肢がありません。

  • オブジェクト参照
  • コレクション
  • 配列

UMLでの表現 Javaでの表現
オブジェクト参照 配列 コレクション
必ず1つ存在 - -
1つ存在するかしないか - -
1以上任意の個数個存在 - -
0以上任意の個数個存在 - -
固定個数個存在 - -
可変個数個存在 -
表2 プロファイル/順序付け


 多重度が1以内の場合(「必ず1つ存在」「1つ存在するかしないか」)、オブジェクト参照として実装されます。これは、通常のマッピングなので特にここでは説明しません。多重度が「可変個数存在」の場合は、コレクションまたは配列で実装することが可能です。 それ以外のケースは、すべてコレクションで実装することが可能です。また、つまり、配列で実装できることはまれなケースということになります。また配列での実装では何かと問題があるので、本プロファイルでは積極的には利用しないことにします。以上の点から、多重度2以上の場合はコレクションを利用して実装するのが本プロファイルの選択となります。

●4.5.3 Javaでの実装(2)

 多重度が2以上の場合、本プロファイルでは配列は使用せずコレクションを用いて実装します。具体的なルールは以下のものです。

  • 型としてインターフェイスjava.util.Collectionを使用する
  • 型を指定したい場合は独自タグ付き値multiplicityInterfaceで指定する
  • 実装クラスのデフォルトとしてクラスjava.util.ArrayListを使用する
  • 実装クラスを指定したい場合は独自タグ付き値collectionClassで指定する

 このルールに沿って図3を実現したJavaプログラムは以下のようになります。

import java.util.Collection;
import java.util.ArrayList;
public class Company {
    private Collection employee = new ArrayList();
}
リスト3 多重度(1)

 また図4に示した独自タグ付き値を実現したJavaプログラムは以下のようになります。 まず、タグ付き値collectionClassで実装クラスとしてLinkedListを指定した場合には以下のようになります。インスタンス変数の型にはデフォルトであるjava.util.Collectionが使用されます。

import java.util.Collection;
import java.util.LinkedList;
public class Company {
    private Collection employee = new LinkedList();
}
リスト4 多重度(2)

 タグ付き値collectionTypeでインスタンス変数の型としてListを指定した場合には以下のようになります。実装クラスにはデフォルトである java.util.ArrayListが使用されます。

import java.util.List;
import java.util.ArrayList;
public class Company {
    private List employee = new ArrayList();
}
リスト5 多重度(3)

 タグ付き値collectionTypeでインスタンス変数の型としてListを、タグ付き値collectionClassで実装クラスとしてLinkedListを指定した場合には以下のようになります。

import java.util.List;
import java.util.LinkedList;
public class Company {
    private List employee = new LinkedList();
}
リスト6 多重度(4)


 次回は今回の続きとして「4.6 順序付け」から解説していきます。

Copyright © ITmedia, Inc. All Rights Reserved.