魔術師見習いのノート

プロフィール

魔術師見習い
Author魔術師見習い-_-.
Twitter魔術師見習い

コンピュータ関係のメモを主に書きます.

MENU

UML2.4(1)

投稿日:
タグ:

UML2.4

構造
ダイアグラム名特徴
オブジェクト図オブジェクト図とは、システムのある時点におけるオブジェクトの静的なスナップショットを表す図。
クラス図クラス同士の静的な関係を表現した図。オブジェクト図を抽象化して記述できる。
コンポジット構造図クラスやコンポーネントの内部構造(クラスやコンポーネント)を表す図。
コンポーネント図ソフトウェアを部品に分解した場合の全体構成を表現する図。
パッケージ図パッケージとパッケージ間の関係を表現する図。
配置図システムの物理的な構成を表現する図。
プロファイル図
動作
ダイアグラム名特徴
アクティビティ図
ユースケース図
シーケンス図
コミュニケーション図
ステートマシン図
タイミング図
相互作用概要図
プログラミング言語よりも抽象的な表現が可能であり、 プログラミング以外にも表現できる。

UML2.4(2) -オブジェクト図-

投稿日:
修正日:
タグ:

オブジェクト図

オブジェクト図とは、システムのある時点におけるオブジェクトの静的なスナップショットを表現するダイアグラムである。

名称意味
オブジェクト
オブジェクト名またはロール名 : クラス名
名前:型名=値
オブジェクト名
ロール名
オブジェクト(インスタンス)を表す要素。クラスを表現する場合もあるが、ロール名及びクラス名に下線がある場合はオブジェクトであることを表す。また、この項目はクラス名を書かず、オブジェクト名だけの場合もある。
スロット
ある時点でのオブジェクトの状態を表す要素
リンク
オブジェクト間に関係があることを表す。

例えば鈴木さんがメンバー加入届けを受付に提出するような場合、次のように表現できる。

鈴木さん メンバー加入届 : 申請書 :受付
  • 名前:文字列=鈴木太郎
  • 住所:文字列=ZZZZZ
  • 電話番号:数=012345
  • 職業:文字列=XXX
import java.util.ArrayList;

class Guest {
  /*- 属性 -*/
  private ApplicationForm memAddAF;

  /*- 操作 -*/
  public Guest(){
    memAddAF = new ApplicationForm("鈴木太郎", "ZZZZZ", 012345, "XXX");
  }
  public ApplicationForm getMemAddAF(){return memAddAF;}
}


class ApplicationForm {
  /*- 属性 -*/
  public String name;
  public String address;
  public int tel;
  public String work;

  /*- 操作 -*/
  public ApplicationForm(String name, String address, int tel, String work){
    this.name = name;
    this.address = address;
    this.tel = tel;
    this.work = work;
  }
}


class Receptionist {
  /*- 属性 -*/

  /*- 操作 -*/
  public void postApplicationForm(ApplicationForm memAddAF){
    // 受付処理
  }
}

class Sample {
  /*- 属性 -*/

  /*- 操作 -*/
  /** エントリポイント */
  public static void main(String args[]){
    Guest suzuki = new Guest();
    Receptionist receptionist = new Receptionist();
    receptionist.postApplicationForm(suzuki.getMemAddAF());
  }
}

UML2.4(3) -クラス図-

投稿日:
修正日:
タグ:

クラス図

クラス図とは、クラス同士の静的な関係を表現した図である。オブジェクト図が処理の流れのある瞬間の関係を表しているのに対し,クラス図は処理の流れ全体を通した関係を示している。クラス図で表現する関係は以下の通りである。

  • 汎化
  • 実現
  • 関連
    • 誘導可能性
    • 集約
    • コンポジション
  • 依存
名称意味
クラス
  • 属性
  • 操作
classA
  • + varA
  • - varB
  • # varC
  • ~ varD
  • + funcA()
  • - funcB()
  • # funcC()
  • ~ funcD()
クラス
オブジェクトの共通部分を抜き出して抽象化したもの。クラスを実体化させたもののことをオブジェクトまたはインスタンスという。クラス図では、クラスはクラスやそのインスタンスを表すのに使用される。
属性
クラスが持つ性質のこと。
操作
クラスが持つ振る舞いのこと。アクセッサ(ゲッタ/セッタ)やコンストラクタの記述は省略される場合がある。
可視性
UMLアクセス指定子(Java)意味
+public全てのクラスからアクセス可能
-private自分のクラスからだけアクセス可能
#protected自分のクラスと継承クラスからのみアクセス可能
~同一パッケージ内からアクセス可能(package)
ローカル可視性
メソッド内だけで繋がること。
属性可視性
オブジェクトが存在している間繋がる長期的な関係のこと。
パラメータ可視性
メソッドの引数として受け取った際だけに繋がる一時的な関係のこと。

インタフェース
Javaのインタフェースを表現する場合、クラス名を<<Interface>>のようにステレオタイプ(<<type>>)で表現。
操作や属性の型を表現する場合、:で区切って右辺に記述する。
  • + 山田太郎 : 人
  • - var : int
  • + func() : boolean
  • + func(arg1 : int) : boolean
初期値
初期値は次のように=を使って表す。
  • + りんごの数 : 非負数 = 5
集約集合-要素の関係。例えば"A has a B"の時,AはBを集約するという意味となる。関連の一種で,JavaではAの属性としてBがある場合にこの記号で表す。
コンポジション集約の中でも強い関係のこと。 例えば"A is part of B"の時,コンポジションで表す。Javaでは,集合クラスのインスタンスが消滅すると、要素クラスのインスタンスも消滅するような関係の時にコンポジションで表現する。
関連
2つのクラスのインスタンス間に長期的な繋がりがあること。Javaでは属性として相手のオブジェクトを持つような場合に関連とする。集約やコンポジションがどちらのクラスの属性なのか明示しているのに対して,関連はどちらかの属性である場合や,それぞれ対等な関係の場合に関連で表現する。
誘導可能性関連がある2つのクラスのインスタンスで一方のクラスがもう一方のクラスを参照(メッセージを送信)できるか否か。参照できる場合は矢印、できない場合は✕印、未定義の場合はそのどちらでもない。Javaで使用する場合,例えば"A has a B"の関係で,かつCがBを属性として保持しなければならない場合で,概念的にはCとBが集約関係でない場合は,誘導可能性で"C→B"のように表現する。これにより,開発者はどちらのクラスの属性かを判断できる。
関連端(ロール)名 属性を関連で表現した場合,属性名や可視性は関連端名で表現する。
多重度 あるクラスの複数のインスタンスと別のクラスのインスタンスに関連がある時、それをまとめることができる。数は次のように表現する。
11
*0以上
1..31以上3以下の範囲
2..*2以上
例えばJavaで配列やコレクションを使用する際に多重度でまとめて表現できる。
依存 2つのクラスが一時的な関係がある時に依存で表現する。Javaでは,引数として一時的にそのクラスを利用するような場合やローカル変数で利用する場合に依存で表現する。例えばクラスAのあるメソッドがクラスBを引数として使用する場合に,"A→B"の方向で記述する。
汎化抽象-具象の関係(class)。 Javaでは"class B extends A"の時,"A→B"の方向で記述する。
実現抽象-具象の関係(interface)。Javaでは"class B implements A"の時,"A→B"の方向で記述する。

以下のコードは記事『UML2.4(2) -オブジェクト図-』 と同じものである。

import java.util.ArrayList;

class Guest {
  /*- 属性 -*/
  private ApplicationForm memAddAF;

  /*- 操作 -*/
  public Guest(){
    memAddAF = new ApplicationForm("鈴木太郎", "ZZZZZ", 012345, "XXX");
  }
  public ApplicationForm getMemAddAF(){return memAddAF;}
}


class ApplicationForm {
  /*- 属性 -*/
  public String name;
  public String address;
  public int tel;
  public String work;

  /*- 操作 -*/
  public ApplicationForm(String name, String address, int tel, String work){
    this.name = name;
    this.address = address;
    this.tel = tel;
    this.work = work;
  }
}


class Receptionist {
  /*- 属性 -*/

  /*- 操作 -*/
  public void postApplicationForm(ApplicationForm memAddAF){
    // 受付処理
  }
}

class Sample {
  /*- 属性 -*/

  /*- 操作 -*/
  /** エントリポイント */
  public static void main(String args[]){
    Guest suzuki = new Guest();
    Receptionist receptionist = new Receptionist();
    receptionist.postApplicationForm(suzuki.getMemAddAF());
  }
}

これをクラス図で抽象的に表現すると次のようになる。

UML2.4(4) -コンポジット構造図-

投稿日:
タグ:

コンポジット構造図

コンポジット構造図とは、クラスやコンポーネントの内部構造を表現するダイアグラムである。コンポジット構造図は次のことを表現できる。

  • クラスやコンポーネントの内部と外部の境界を表現できる。
  • クラスやコンポーネント内のクラスやコンポーネントの結びつきや役割を表現できる。
名称意味
クラス
クラス名
内部構造を表現したいクラスやコンポーネントはこの図で表す。
クラス
オブジェクトを抽象化したもの。
コンポーネント
インタフェースを持つクラス。
コンポーネント
パート
部品
クラスやコンポーネントを構成する内部要素。部品のこと。パートもまたクラスやコンポーネントである。ロール名や多重度を表現可能。
コネクタ
パート間に関係があることを示す。
ポート
クラス(またはコンポーネント)の内部と外部の境界を表す。
インタフェース
提供インタフェース
クラスやコンポーネントが外部に公開している機能を表す。
要求インタフェース
クラスやコンポーネントが必要とする外部機能を表す。

例えばMP3とWMA形式、生の音楽ファイル(例えばWAV)を再生する音楽プレイヤーを表現したものが、以下のコンポジット図である。

/* 音楽プレイヤー */
class MusicPlayer {
  private ArrayList<Audio> playlist;
  private Controller my_controller;
  public GInterface my_interface;
  MusicPlayer(){
    playlist 
      = new ArrayList<Audio>(); 
    my_controller 
      = new Controller(playlist);
    my_interface
      = new GInterface(my_controller);
    my_interface.setVisible(true);
  }
}
前述のサンプルコードの全体像は次の通りである(曲の制御部分については省略)。
import java.util.ArrayList;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.*;

/* 音楽 */
class Audio {
  public final String name;
  public final String path;
  Audio(String n, String p){
    name = n;
    path = p;
  }
}

/* コントローラ */
class Controller {
  private ArrayList<Audio> playlist;
  private int current_idx = 0;
  public Controller(ArrayList<Audio> pl){
    playlist = pl;
  }
  public void addAudio(Audio audio){
    playlist.add(audio);
  }
  public void start(){
    playlist.get(current_idx);
    /* 再生処理 */ 
  }
  public void stop(){
    /* 停止処理 */
  }
  public void next(){
    /* 次の曲へ */
  }
  public void prev(){
    /* 前の曲へ */
  }
}

/* インタフェース */
class GInterface extends JFrame {
  Controller controller;
  JButton start;
  JButton stop;
  JButton prev;
  JButton next;
  JButton adda;
  class StartListener implements ActionListener {
    public void actionPerformed(ActionEvent e){
      controller.start();
    }
  }
  class StopListener implements ActionListener {
    public void actionPerformed(ActionEvent e){
      controller.stop();	    
    }
  }
  class NextListener implements ActionListener {
    public void actionPerformed(ActionEvent e){
      controller.next();	    	    
    }
  }
  class PrevListener implements ActionListener {
    public void actionPerformed(ActionEvent e){
      controller.prev();	    	    	    
    }
  }
  class AddListener implements ActionListener {
    public void actionPerformed(ActionEvent e){
      JFileChooser filechooser = new JFileChooser();
      FileNameExtensionFilter filter = new FileNameExtensionFilter("mp3 & wma & wav audio file", "mp3", "wma", "wav");
      filechooser.setFileFilter(filter);
      if (filechooser.showOpenDialog(GInterface.this)==JFileChooser.APPROVE_OPTION)
        controller.addAudio(
          new Audio( filechooser.getSelectedFile().getName(),
               	     filechooser.getSelectedFile().getPath()));
    }
  }
  GInterface(Controller ctr){
    super();
    controller = ctr;
    start = new JButton("再生");
    start.addActionListener(new StartListener());
    stop = new JButton("停止");
    stop.addActionListener(new StopListener());
    prev = new JButton("前へ");
    prev.addActionListener(new PrevListener());
    next = new JButton("次へ");
    next.addActionListener(new NextListener());
    adda = new JButton("曲を追加");
    adda.addActionListener(new AddListener());
    Container c = this.getContentPane();
    c.setLayout(new GridLayout(1,5));
    c.add(prev);
    c.add(start);
    c.add(stop);
    c.add(next);
    c.add(adda);
    this.setSize(500, 100);
  }
}

/* 音楽プレイヤー */
class MusicPlayer {
  private ArrayList<Audio> playlist;
  private Controller my_controller;
  public GInterface my_interface;
  MusicPlayer(){
    playlist = new ArrayList<Audio>(); 
    my_controller = new Controller(playlist);
    my_interface = new GInterface(my_controller);
    my_interface.setVisible(true);
  }
}

UML2.4(5) -コンポーネント図-

投稿日:
タグ:

コンポーネント図

コンポーネント図とは、コンポーネントの構造を表現するダイアグラムであり、ソフトウェアを部品に分解した場合の全体構成を表現する。コンポーネント図は、各部品の内部構造には着目せず、外部に公開している機能、外部に要求している機能だけに着目する。

名称意味
コンポーネント
  • 《component》
  • コンポーネント名
コンポーネントは入れ子構造であり、内部にいくつかのコンポーネントを記述できる。
  • 《component》
  • コンポーネント名
インタフェース
提供インタフェース
外部に公開する機能を表す。白丸(ボール)で表記。
要求インタフェース
外部に要求する機能を表す。半円(ソケット)で表記。
実現 あるコンポーネントが別のコンポーネントを利用していることを表す。

UML2.4(6) -パッケージ図-

投稿日:
修正日:
タグ:

パッケージ図

パッケージ図は、パッケージとパッケージ間の関係を表現するダイアグラムである。

名称意味
パッケージ
パッケージ
さまざまなダイアグラムをグループ化するための要素のことであり、名前空間の管理も行う。パッケージ内の各要素の関係は、クラス図やコンポジット構造図のような他のダイアグラムで表現でき、パッケージ間の関係はインポートやマージで表現できる。
パッケージ
要素
インポート 別のパッケージに含まれている要素(クラスやインタフェースなど)を読み込むことを表す。矢印がA⇢BならばパッケージAがパッケージBを読み込んでいることを示す。
マージ 既存のパッケージを利用して別のパッケージを新規に作成することを表す。マージとインポートの違いはパッケージ間で名前の衝突が発生した時の解決方法である。
インポート
インポートするパッケージに元々あった要素が隠される。
マージ
両方のクラスの特徴を持つクラスが生成される。

次のようなパッケージ図があるとする。この時、パッケージP0でクラスAの操作opAという定義があり、かつそれをインポートしたパッケージP1でクラスAの操作Bを定義した場合、パッケージP0のクラスAは隠蔽され、P3で利用するクラスAは操作opBしかない。もしパッケージP0をマージしたパッケージP2でクラスAの操作Bを定義した場合、それをインポートしたパッケージP4では操作opAと操作opBの2つの機能を持つクラスとなる。


Javaのパッケージ

Javaでは、パッケージのインポートをimport文を用いて行う。パッケージの生成とimportは次のように行う。

./pkgtest/Hoge.java
パッケージを生成し、そのパッケージにファイル内で定義したクラスやインタフェースを追加する場合、package文を使用する。package文は必ずJavaの本文を記述する前に記述しなければならない。Javaでは,package文を省略した場合は無名パッケージとして扱われる。すなわちJavaのクラスは必ずいずれかのパッケージに属する。
package pkgtest; // 登録

/**
 * クラスHogeの説明
 * @author 魔術師見習い
 */
public class Hoge {
 /**
  * 加算関数
  * @param addee 被加数
  * @param adder 加数
  * @return 加算結果
  */
  public int add(int addee, int adder){
    return addee + adder;
  }
}
./pkgtest/package-info.java
javadocを使用する場合、パッケージの説明はpackage-info.javaというファイルに記述する。
/**
 * パッケージpkgtestの説明
 * 
 */
package pkgtest;
./Fuga.java
パッケージは次のようにimport文を使用して行う。
import pkgtest.Hoge;

public class Fuga {
  public static void main(String args[]){
    Hoge h = new Hoge();
    System.out.println(h.add(1, 3));
  }
}

UML2.4(7) -配置図-

投稿日:
タグ:

配置図

配置図は、システムの物理的な構成を表現するダイアグラムである。

名称意味
ノード ハードウェアや実行するソフトウェアなどの実行するモノの単位。
ステレオタイプ
device
ハードウェア
executionEnvironment
ソフトウェア実行環境
ノードは入れ子構造であり、ノード内にノードや成果物を記述できる。実際のハードウェアそのものを指している場合はノード名に下線を引く。
コミュニケーションパス
ノード間に物理的な繋がりがあること。関係に方向性がある場合、矢印でその方向を示す。
成果物 ソフトウェア開発の各工程で生成された物理的な情報の単位。ソースファイルや実行ファイル、データベースのテーブル定義などのような実際にノードに配置する配布単位を表現する(例:DBサーバ、hoge.exe)。
依存あるノードや成果物が別のノードや成果物を利用していること。依存する側から依存される側に向かって矢印を記述。

ワークステーションAの/usr/bin/javaでHogeというプログラムを実行し、それがワークステーションBのDBサーバを利用していることを表した図は次のように記述できる。

UML2.4(8) -プロファイル図-

投稿日:
タグ:

プロファイル図

UMLの内容を独自に拡張するためのダイアグラムで、メタモデルの構築が行える。

名称意味
メタクラス
《Metaclass》
メタクラス
クラスのためのクラスのこと。
ステレオタイプ
《stereotype》
ステレオタイプ
モデル要素に特別な意味をもたせ、特定の用途にモデル要素を拡張して使用することを表す。
プロファイル
《profile》
プロファイル
UMLを拡張するための特殊パッケージ。
《profile》
プロファイル
拡張 メタクラスの拡張。
プロファイル適用 外部のプロファイルの適用。

UML2.4(11) シーケンス図

投稿日:
タグ:

シーケンス図

シーケンス図とは,オブジェクト(クラス)間の相互関係を時系列的に表現したダイアグラムのことである。 シーケンス図の構成要素は次の通りである。

実行指定
オブジェクトの操作が呼び出されている時間。
ライフライン
使用されていないがオブジェクトがまだ存在していることを表す。
メッセージ
同期メッセージ
呼び出し先の処理が終わる(返事が返ってくる)のを待って,処理を行う場合のメッセージパッシング。
リプライメッセージ
返事。処理が終わったことを伝えるためのメッセージ。
reply
非同期メッセージ
呼び出し先の処理を待たずに処理の継続や処理の終了を行う場合のメッセージパッシング。
複合フラグメント
種類説明
loop繰り返し文
alt条件文
ステレオタイプ

分析

概念クラス図
概念シーケンス図

設計

実装クラス図
実装シーケンス図

実装

Book.java
class Book {
  /*- 属性 -*/
  /** タイトル。 */
  private String title;
  /** 著者。 */
  private String author;

  /*- 操作 -*/
  /**
   * コンストラクタ。
   * @param title タイトル。
   * @param author 著者。
   */
  Book(String title, String author){
    this.title = title;
    this.author = author;
  }

  /**
   * 本のタイトルを取得。
   * @return 本のタイトル。
   */
   public String getTitle(){
     return this.title;
   }

  /**
   * 本の著者を取得。
   * @return 本の著者。
   */
   public String getAuthor(){
     return this.author;
   }
}
Library.java
import java.util.*;

class Library {
  /*- 属性 -*/
  /** 図書館名。 */
  private String name;
  /** 住所。 */
  private String address;
  /** 本リスト。 */
  private ArrayList<Book> book_list;


  /*- 操作 -*/
  /**
   * コンストラクタ。
   * @param name 図書館名。
   * @param address 住所。
   */
  public Library(String name, String address){
    this.name = name;
    this.address = address;
    this.book_list = new ArrayList<Book>();
  }

  /**
   * 本を借りる。
   * @param title 借りたい本のタイトル。
   */
  public Book lendBook(String title){
    Book book = searchBook(title);
    if (book!=null){
      this.book_list.remove(book);
      return book;
    }else{
      return null;
    }
  }
  
  /**
   * 本を追加する。
   * @param book 追加する本
   */
  public void addBook(Book book){
    this.book_list.add(book);
  }

  /**
   *
   */
  private Book searchBook(String title){
    Iterator<Book> it = this.book_list.iterator();
    while (it.hasNext()){
      Book book = it.next();
      if (book.getTitle()==title){
        return book;
      }
    }
    return null;
  }
}
Client.java
class Client {
  /*- 属性 -*/
  private Library lib;
  
  /*- 操作 -*/
  /** エントリポイント */
  public static void main(String args[]){
    Client client = new Client();
    client.init();
    client.exec();
  }
  /** デフォルトコンストラクタ。 */
  public Client(){
  }
  /** 1つ目の実行指定 */
  private void init(){
    final String[][] BOOKS = {{"たいとるA", "山田太郎"},
                              {"たいとるB", "鈴木次郎"},
                              {"たいとるC", "佐藤三郎"}};

    lib = new Library("市立図書館", "XXX-YYY ○○市△△町1-1-1");
    
    for (String[] book : BOOKS){
      lib.addBook(book[0], book[1]);
    }
  }
  /** 2つ目の実行指定 */
  private void exec(){
    lib.lendBook("たいとるB");
  }
};

一覧