C++とUMLのクラス図

増補改訂版Java言語で学ぶデザインパターン入門UMLのクラス図で

  1. 継承
  2. 集約
  3. インターフェース
  4. 関連
    1. Uses
    2. Creates
    3. Notifies

ぐらいしか使っていないんだけど、自分の場合はほとんどのクラス図でこれで十分なような気がしてきた。

継承

車は、乗り物(Vehicle)を継承する。

// -*- coding: utf-8-unix -*-
digraph inherit {
  graph [fontname = "monospace", fontsize = 10, rankdir = TD];
  node  [fontname = "monospace", fontsize = 10];
  edge  [fontname = "monospace", fontsize = 10];

  // node
  node          [shape = record];
  vehicle_class [label = "{Vehicle||}"];
  car_class     [label = "{Car||}"];
  vehicle       [label = "class Vehicle"];
  car           [label = "class Car : Vehicle"];

  // edge
  edge [arrowhead = none, arrowtail = onormal];
  vehicle_class -> car_class;
  vehicle       -> car;
  
  // rank
 {rank = same; car_class;     car}
 {rank = same; vehicle_class; vehicle}
}

集約

車(Car)は、車輪(Wheel)のインスタンスを持つ。

// -*- coding: utf-8-unix -*-
digraph aggregation {
  graph [fontname = "monospace", fontsize = 10, rankdir = TD];
  node  [fontname = "monospace", fontsize = 10];
  edge  [fontname = "monospace", fontsize = 10];

  // node
  node        [shape = record];
  car_class   [label = "{Car||}"];
  wheel_class [label = "{Wheel||}"];
  car         [label = "class Car \{\l  Wheel wheel[];\l\}\l"];
  wheel       [label = "class Wheel"];

  // edge
  edge [arrowhead = none, arrowtail = odiamond, label = "1 .. n"];
  car_class -> wheel_class;
  car       -> wheel;
  
  // rank
 {rank = same; car_class;     car}
 {rank = same; wheel_class; wheel}
}

インターフェース

運転できるもの(Driable)は、発進l(run)と停止(stop)ができる。どう実現するかサブクラスが定義しなければならない。

// -*- coding: utf-8-unix -*-
digraph interface {
  graph [fontname = "monospace", fontsize = 10, rankdir = TD];
  node  [fontname = "monospace", fontsize = 10];
  edge  [fontname = "monospace", fontsize = 10];

  // node
  node           [shape = record];
  drivable_class [label = "{\<\<interface\>\>\nDrivable||run()\lstop()\l}"];
  drive_class    [label = "{Drive||run()\lstop()\l}"];
  drivable       [label = "\
class Drivable \{  \l\
  virtual run();   \l\
  virtual stop();  \l\
\}                 \l\
"];
   drive         [label = "\
class Drive : Drivable \{ \l\
 run() \{/* */\};         \l\
 stop() \{/* */\};        \l\
\}                        \l\
"];

  // edge
  edge [arrowhead = none, arrowtail = onormal, style = dashed];
  drivable_class -> drive_class;
  drivable       -> drive;
  
  // rank
 {rank = same; drivable_class; drivable}
 {rank = same; drive_class;    drive}
}

関連

Uses

描画クラス(Draw)は波を書くとき、Mathクラスのsin()を使う。

// -*- coding: utf-8-unix -*-
digraph relation_use {
  graph [fontname = "monospace", fontsize = 10, rankdir = TD, nodesep = 0.5];
  node  [fontname = "monospace", fontsize = 10];
  edge  [fontname = "monospace", fontsize = 10];

  // node
  node           [shape = record];
  draw_class [label = "{Draw||draw_wave()}"];
  math_class    [label = "{Math||sin()\l}"];
  draw       [label = "\
class Draw \{    \l\
  draw_wave() \{ \l\
    Math m;      \l\
    m.sin();     \l\
    ...          \l\
  \}             \l\
\}               \l\
"];
   math         [label = "\
class Math \{     \l\
 sin() \{/* */\}; \l\
\}                \l\
"];

  // edge
  edge [arrowhead = vee, arrowtail = none];
  draw_class -> math_class [taillabel = "Uses\>", labelangle = 10, labeldistance = 6];
  draw       -> math       [label     = "Uses\>"];

    edge [arrowhead = none, arrowtail = none, style = invis, label = ""];
    draw_class -> draw;
    math_class -> math;

  // rank
 {rank = same; draw_class; math_class}
 {rank = same; draw; math}
}
Creates

シェフ(Chef)は、料理(Dish)を作る。

// -*- coding: utf-8-unix -*-
digraph relation_create {
  graph [fontname = "monospace", fontsize = 10, rankdir = TD, nodesep = 0.5];
  node  [fontname = "monospace", fontsize = 10];
  edge  [fontname = "monospace", fontsize = 10];

  // node
  node       [shape = record];
  chef_class [label = "{Chef||cook()\l}"];
  dish_class [label = "{Dish||}"];
  chef       [label = "\
class Chef \{             \l\
  cook() \{               \l\
    Dish dish = new Dish; \l\
    ...                   \l\
  \}                      \l\
\}                        \l\
"];
  dish       [label = "class Dish"];

  // edge
  edge [arrowhead = vee, arrowtail = none];
  chef_class -> dish_class [taillabel = "Creates\>", labelangle = 10, labeldistance = 6];
  chef       -> dish       [label     = "Creates\>"];

  edge [arrowhead = none, arrowtail = none, style = invis, label = ""];
  chef_class -> chef;
  dish_class -> dish;

  // rank
 {rank = same; chef_class; dish_class}
 {rank = same; chef; dish}
}
Notifies

客(Client)はタクシー(Taxi)を呼ぶ。

// -*- coding: utf-8-unix -*-
digraph relation_notify {
  graph [fontname = "monospace", fontsize = 10, rankdir = TD, nodesep = 0.5];
  node  [fontname = "monospace", fontsize = 10];
  edge  [fontname = "monospace", fontsize = 10];

  // node
  node         [shape = record];
  client_class [label = "{Client||call_taxi()\l}"];
  taxi_class   [label = "{Taxi||}"];
  client       [label = "\
class Client \{            \l\
  call_taxi() \{           \l\
    Message message;       \l\
    message.number = TAXI; \l\
    message.send();        \l\
  \}                       \l\
\}                         \l\
"];
  taxi [label = "class Taxi"];

  // edge
  edge [arrowhead = vee, arrowtail = none];
  client_class -> taxi_class [taillabel = "Notifies\>", labelangle = 10, labeldistance = 6];
  client       -> taxi       [label     = "Notifies\>"];

  edge [arrowhead = none, arrowtail = none, style = invis, label = ""];
  client_class -> client;
  taxi_class   -> taxi;

  // rank
 {rank = same; client_class; taxi_class}
 {rank = same; client; taxi}
}