第12回 静的モデル:アソシエーションのUML部品のまとめJavaオブジェクトモデリング

 今回は、アソシエーションの残りの付加情報「変更可能性(changeability)」「限定子(qualifier)」「インターフェイス指定子(interface specification)」まで解説し、アソシエーションにおけるUMLの部品の解説をまとめます。

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

■■2.9 変更可能性■■

意味
なし 変更可
frozen 変更不可
addOnly 追加のみ可能
表 変更可能性

 変更可能性(changeability)は、アソシエーションを実体化したモデル要素であるリンクの変更が可能であるかを示しています。表に示すとおり、「変更可能性なし」「frozen」「addOnly」の3つの値を持ちます。

 変更可能性なしは、リンクを変更できる通常のアソシエーションです。変更可能性frozenは、リンクを変更することができないアソシエーションであることを示します。変更可能性addOnlyは、リンクの追加のみを行うことが可能なアソシエーションであることを示しています。変更可能性addOnlyは、その意味上、多重度が“1で固定”以外のときに有効となります。

●2.9.1 UMLでの表現

 UMLでは、変更可能性は図1に示すように制約frozenまたは制約addOnlyを用いて表現します。

ALT 図1 変更可能性

●2.9.2 Javaでの実現/frozen

 変更可能性は、多重度の設定によって、Javaでの実現方法が変わってきます。まず変更可能性frozenの場合について考えます。まず、多重度が1の場合です。変更可能性の指定がない場合のクラスCompanyの実装はリスト1のようになります。

リスト1 変更可能性なし


public class Company {
    private Person employee;
}

 それに対して、変更可能性がfrozenの場合のクラスCompanyの実装は修飾子finalを使います。finalを設定されたインスタンス変数は、以下のいずれかの方法でのみ値を設定することができます。

  • インスタンス変数の初期値
  • コンストラクタで設定

 つまり、修飾子finalを指定することでオブジェクトの生成後にインスタンス変数の変更が行われるのを防げるわけです。修飾子finalを使用した場合の、インスタンス変数の初期化の例を以下に示します。

リスト 2 変更可能性/frozen/初期値として設定


public class Company {
    private final Person employee = new Person();
}

リスト 3 変更可能性/frozen/コンストラクタで設定


public class Company {
    private final Person employee;
    public Company(Person employee) {
        this.employee = employee;
    }
}

 次は多重度が2以上の場合です。多重度が2以上の場合には、配列かコレクションを使ってオブジェクトの集まりを管理することになるため、変更可能性の実装方法が変わってきます。

 変更可能性の指定がない場合のクラスCompanyの実装は以下のようになります。そして、変更可能性がfrozenであった場合も、インスタンス変数の実装方法は変わりません。なぜなら、インスタンス変数employeeに修飾子finalを指定しても、コレクションの内容の変更を防ぐことはできないからです。

リスト 4 変更可能性/指定なし


public class Company {
    private Collection employee = new ArrayList();
}

 つまり、多重度が2以上の場合、変更可能性frozenはJavaの基本機能では直接実装することができないのです。このため、以下に示すようにプログラム的な作り込みが必要となります。

リスト 5 変更可能性/frozen


public class Company {
    private Collection employee = new ArrayList();
    public Company(Employee[] employees) {
        employee.addAll(Arrays.asList(employees));
    }
    public Employee[] getEmployees() {
        Employee[] employees = new Employee[employee.size()];
        return ((Employee[])employee.toArray(employees));
    }
}

 この実装では、

  • インスタンス変数employeeはアクセスの範囲を非公開
  • 設定のタイミングはコンストラクタによるオブジェクトの初期化時のみ
  • 内容の参照のみpublicなメソッドgetEmployeeを通して可能とする

ことで、frozenの意図である「リンクが変更されないこと」を実現しています。

●2.9.3 Javaでの実現/addOnly

 変更可能性addOnlyは多重度「1」では意味を持ちません。また、多重度が「0、1」と「2以上」で実装方法が変わってきます。

 

 まず多重度が「0、1」の場合です。

 

 この場合は、以下のような実装になります。変更可能性addOnlyの意図を実現するため、1度だけPersonオブジェクトを設定できることを保証するようにsetEmployeeメソッドが実装されています。つまり、変更可能性frozenの多重度2以上の場合と同様に、Javaの基本機能だけでは表現することができないため相応の作り込みが必要となります。

リスト 6 変更可能性/addOnly/多重度「0、1」


public class Company {
    private Person employee = null;
    public void setEmployee(Person employee) {
        if (this.employee == null) {
            throw (new IllegalStateException("Employee has already existed"));
        this.employee.add(employee);
    }
}

 次は、多重度が「2以上」の場合です。この場合は、リンクの管理にコレクションを使うことになります。このとき、“コレクションに追加しか許さない”ということをaddEmployeeメソッドのみを提供することで実現しています。

リスト 7 変更可能性/addOnly


public class Company {
    private Collection employee = new ArrayList();
    public void addEmployee(Person employee) {
        this.employee.add(employee);
    }
}

 以上、変更可能性addOnlyについて検討しました。変更可能性frozenの場合と同様、変更可能性addOnlyの実現も、Javaの基本機能だけでは難しいことが分かりました。

 変更可能性frozen、変更可能性addOnlyのいずれの場合も、Javaでの実装では相応の作り込みが必要になることが分かりました。プログラムとして作り込む内容はその時々の状況によって変わってくるため、定型的なマッピングは難しいといえます。

■■2.10 限定子■■

 限定子(qualifier)は、アソシエーション・エンドに関連付けられたオブジェクトの集合に対して、その一部を特定するための情報を提供する属性または属性のリストです。

●2.10.1 UMLでの表現

 限定子を使ったアソシエーションの例を図2に示します。

ALT 図2 限定子

 参照側のクラスに関連付けられているアソシエーション・エンドに限定子を記述します。なお、Javaとのマッピングを考える場合、型も明記する必要があります。

●2.10.2 Javaでの実現

 限定子をJavaで実現する典型的な方法はコレクションのマップ機能を使うことです。具体的にはインターフェイスとしてjava.util.Mapを、具象クラスとしてjava.util.HashMapやjava.util.TreeMapなどを利用します。

リスト 8 変更可能性/addOnly


import java.util.Map;
import java.util.HashMap;
public class Company {
    private Map employee = new HashMap();
}

■■2.11 インターフェイス指定子■■

 インターフェイス指定子は、アソシエーション・エンドに関連付けられているオブジェクトに期待されている振る舞いを定義するためのインターフェイスを定義する機能です。

●2.11.1 UMLでの表現

 図3はインターフェイス指定子の例です。ロール名の後ろに、アソシエーション・エンドに関連付けられているインターフェイスが定義されています。

ALT 図3 インターフェイス指定子

●2.11.2 Javaでの実現

 図3に示すインターフェイス指定子のJavaでの実装は以下のようになります。インターフェイス指定子で指定されたインターフェイスIEmployeeがインスタンス変数の型となります。そして、そのインスタンス変数からはクラスEmployeeが参照されます。

リスト 9 インターフェイス指定子


public class Company {
    private IEmployee employee = new Employee();
}

■■2.12 UML部品のまとめ■■

 4回にわたって、アソシエーションに関するUML部品についてまとめました。UMLのアソシエーションは、大きく以下の3つの部品から構成されています。

  • アソシエーション本体
  • アソシエーション・エンド
  • 限定子を示す属性

 この中で重要なのがアソシエーション・エンドです。限定子を示す属性もアソシエーション・エンドの一部です。本節ではアソシエーション・エンドを構成する以下の部品についてJavaとのマッピングについて整理しました。

  • ロール名(rolename)
  • 誘導可能性(isNavigable)
  • 可視性(visibility)
  • ターゲット・スコープ(目標範囲、targetScope)
  • 集約(aggregation)
  • 多重度(multiplicity)
  • 順序付け(ordering)
  • 変更可能性(changeability)
  • 限定子(qualifier)
  • インターフェイス指定子(interface specification)

 この中で、Javaをターゲットにした設計モデルの記述のうえで必須となるのが、ロール名、誘導可能性、可視性、ターゲット・スコープです。また、集約、多重度、順序付け、変更可能性、限定子、インターフェイス指定子は付加情報として利用することになります。


 以上、アソシエーションに関するUML部品について解説をしてきましたが、次回からはアソシエーションに関するJava部品の詳細の解説に移っていきます。

Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ