概念: 構造化クラス
トピック
定義
UML ([UML04]) では、クラスは EncapsulatedClassifier およびメタクラス Class の両方のサブタイプです。メタクラス Class により、内部構造とポートを保持する機能がクラスに提供されます。
また、UML では、コンポーネントはクラスのサブタイプとして定義されます。
したがって、RUP のコンテキストでは、コンポーネントおよびクラスを両方とも構造化クラスとして扱います。
パーツ
構造化クラスのインスタンスには、各パーツに対応する 1 つのオブジェクトまたは複数のオブジェクトのセットが含まれます。
収容構造化クラス・インスタンスが破棄されると、これらのインスタンスもすべて破棄されます。
以下の例は、Car (車) クラスの 2 つの可能なビューを示します。
図 (a) では、Car は、役割名 rear (後部) のコンポジション関係をクラス Wheel (ホイール) に対して持ち、役割名 e のコンポジション関係をクラス Engine (エンジン) に対して持ちます。
クラス Engine の任意のインスタンスを、クラス Wheel の任意の数のインスタンスにリンクできます。
図 (b) でも同じ内容が指定されます。
ただし、図 (b) では、以下の指定が追加されています。
-
rear および e は、クラス Car の内部構造に属しています。
これにより、クラス Car のコンテキスト内の Wheel クラスと Engine クラスのインスタンスでのみ有効な詳細を指定できます。この詳細は、一般のホイールやエンジンには適用されません。
-
クラス Car のコンテキスト内では、e の役割を持つインスタンスは、rear の役割を持つ 2 つのインスタンスにのみ接続できます。
また、e および rear の役割を持つインスタンスは、クラス Car の同じインスタンスの役割である場合にのみリンクできます。
つまり、クラス Wheel および Engine のインスタンスがクラス Car のインスタンス内でそれぞれの役割を持っている場合は、各クラスのインスタンスに追加制約が適用されます。
これらの制約は、一般の Wheel および Engine のインスタンスには適用されません。
ほかのホイールおよびエンジンは、図 (a) で指定されているように任意にリンクできます。

例: 構造化クラスの内部で役割を持つパーツ
コネクター
コネクターは、構造化クラス内の 2 つのパーツの間の関係のインスタンスです。
このリンクにより、コミュニケーションが可能になります。
コネクターは、通常の関連または一時関係 (プロシージャー・パラメーター、変数、グローバル値などのメカニズム) によって実装できます。
構造化クラスの内部「配線」は、アセンブリー・コネクターと委譲コネクターによって指定されます。
- 構造化クラスの実装の内部で、アセンブリー・コネクターは、複数のパーツのポートを接続します。
1 つの構造化クラスのポート上で送信されたメッセージは、別の構造化クラスの接続されたポート上で受信されます。
パーツのポートを通じて、複数のパーツを相互に関連付けることができます。
パーツがほかのパーツを認識する必要はありません。ただし、ほかのパーツが存在し、接続されたポート上での制約を満たしていることは確認する必要があります。
構造化クラス相互のコミュニケーションは、各クラスのポートによってモデリングされます。
- 委譲コネクターは、構造化クラスの外部ポートを、そのクラスの内部パーツの 1 つのポートに接続します。
外部ポートが受信したメッセージは、内部パーツ上のポートに渡されます。内部ポートが送信したメッセージは、外部ポートに渡され、その後で外部ポートに接続された構造化クラスに渡されます。
ポート
ポートは、構造化クラスの構造特性の 1 つです。
構造化クラスの外部からのコミュニケーションが宣言済みのインターフェースに従ってポートを通過するように強制することにより、カプセル化を促進できます。これにより、その構造化クラスの指定の精度が向上し、相互接続が実現されます。
ポートの必須インターフェースと提供インターフェースは、その相互作用ポイントを通過する相互作用に必要なすべての情報を指定します。
1 つの構造化クラスとその環境との間のすべての相互作用がポートを通じて実現する場合、その構造化クラスの内部は環境から完全に分離されます。
このような構造化クラスは、そのポートが指定する制約を満たす任意のコンテキスト内で使用できます。
ポートの実装方法についての仮定はありません。
ポートは、明示的なオブジェクトとしても実装できます。実装内に明示的に出現しない単なる仮想概念である場合もあります。
ポートの例を以下に示します。
例 1

Car と Boat によって使用される Engine のポート
上の図は、ポート p と以下の 2 つのインターフェースを持つクラス Engine を示します。
- 提供インターフェース powertrain (動力伝達機構) は、エンジンがこのポートで提供するサービス (つまり、このポートに到達したコミュニケーションによってアクセス可能な操作および受信) を指定します。
- 必須インターフェース power (動力) は、エンジンの環境からエンジンに提供する必要のあるサービスを指定します。
ポート p では、Engine クラスは完全にカプセル化されます。このクラスは、このエンジンが埋め込まれる環境を考慮せずに指定できます。
エンジンの提供インターフェースおよび必須インターフェースによって表現される制約に環境が従っている限り、エンジンは適切に機能します。
このことを示すために、Engine クラスの 2 つの使用例を以下に示します。
- Car クラスは、エンジンのポート p を、axle (車軸) を介して複数のホイールに接続します。
- Boat クラスは、エンジンのポート p を、shaft (シャフト) を介してプロペラに接続します。
Engine とそのポート p にリンクされたパーツとの間の相互作用が、提供インターフェースおよび必須インターフェースが指定する制約に従っている限り、車のエンジンまたはボートのエンジンのいずれであっても、エンジンは指定どおりに機能します。
さらに、Engine にほかの宣言済みポート (Fuel Consumption (燃料消費量) のポート f など) がある場合でも、車のホイールおよびボートのプロペラは、Engine にポート p を通じてアクセスできます。ポート f は燃料計に関連しますが、使用されている燃料の種類や、車およびボートに付いている燃料計の種類とは無関係です。
例 2
このポートの例は、Java Logging API ([JAV03]) に基づいています。Java Logging API は、以下のものを含む Java 2 プラットフォームのコア・ロギング機能のクラスおよびインターフェースを提供するパッケージです。
Logger (ロガー) は、アプリケーションがロギング呼び出しを行うメイン・エンティティーです。
これは、特定のシステムまたはアプリケーション・コンポーネントのメッセージをロギングするために使用されます。
Level (レベル) は、ログ・メッセージの重要度および緊急度の指針を提供します。
Filter (フィルター) は、ロギングする対象について、ログ・レベルで提供されるコントロールよりも詳細なコントロールを提供します。
Handler (ハンドラー) は、ロガーから受け取ったメッセージをさまざまな宛先 (メモリー、出力ストリーム、コンソール、ファイル、およびソケット) にエクスポートします。
Formatter (フォーマッター) は、ログ・レコードのフォーマット処理のサポートを提供します。
以下のクラスおよびインターフェースは、2 種類の重要なコラボレーションに関連します。
ログへの書き込みに使用されるクラスおよびインターフェースと、ログの管理に使用されるクラスおよびインターフェースとがあります。
以下の図は、クライアントおよび管理者とログとの間の 2 種類のコラボレーションを示します。これらのコラボレーションは、UML コラボレーションとしてモデリングされています。
Writing (書き込み) コラボレーション。ログへの書き込みのために、LogClient 役割を LogWriter 役割に接続します。
Administration (管理) コラボレーション。ログへのアクセスおよびログ設定の変更のために、LogAdministrator 役割を LogController 役割に接続します。

クライアントおよび管理者とログとの間のさまざまなコラボレーション
ロギング・サービスおよびそのコラボレーションをモデリングする UML 2.0 表現方法の 1 つは、ポートと宣言済みインターフェースを持つコンポーネントを使用することです。以下の図に例を示します。

ポートとしてグループ化した提供インターフェースを持つコンポーネントとして Java Logging API パッケージを実装
Java Logging API 仕様では、一部のロギング・サービスがクラスとして、その他のロギング・サービスがインターフェースとして実装されました。
この例では、これらの各サービスを提供インターフェースとしてモデリングします。提供インターフェースは、コンポーネントの内部にあるパーツによって実現されます。
上記の Writing および Administration コラボレーションに関連する 2 種類の振る舞いは、ポートとして論理的にグループ化されたインターフェースによって表すことができます。
したがって、以下のようにします。
Logger および Level インターフェースを LogWriter ポートとしてグループ化します。
これらのインターフェースには、ログ・クライアントがログに書き込むためにアクセスできます。
Handler、Filter、および Formatter インターフェースを LogController ポートとしてグループ化します。
これらのインターフェースには、ログ管理者がログにアクセスしたりログ設定を変更したりするためにアクセスできます。
この代替モデリング方法では、いくつかのポートとしてインターフェースを論理的にグループ化することにより、問題が分離されます。
これにより、コンポーネント指定の精度が向上し、そのコンポーネントと外部環境との相互接続が実現されます。
モデリング
設計中に、クラスおよびコンポーネントを、接続されたパーツのコレクションに分解できます。このコレクションはさらに分解することができます。
複合構造図を使用して、構造化クラスの分解を示すことができます。
たとえば、以下の図は、チケット発行システムのチケット売場の複合構造図を示します。
このクラスは、3 つのパーツに分解されます。
- チケット販売者のインターフェース
- 日付などの基準に基づいて演目を検索する演目ガイド
- 演目およびチケットについてのデータを格納する複数のデータベース
各パーツは、そのポートによって指定された明確に定義されたインターフェースを通じて相互作用します。
チケット売場全体としては、ポートを通じて外部環境と相互作用します。
このポート上のメッセージは ticket seller (チケット販売者) クラスにディスパッチされますが、box office (チケット売場) クラスの内部構造は外部クライアントから隠蔽されています。

例: チケット発行システムの複合構造図。
UML 1.x 表現
構造化クラスは UML 2.0 での新しい概念であることに注意してください。
「 成果物: カプセル」および「 ガイドライン: カプセル」には、UML 1.5 のみをサポートするツールを使用する場合の代替表現の説明もあります。
詳細については、「UML 1.x と UML 2.0 の相違」を参照してください。
|