🎃
mermaidのクラス図メモ
mermaidでUMLを書く際のメモをサンプルコードと共に残しておきます。
クラス図
クラス間の関係
記号 | 意味 | サンプル |
---|---|---|
<|-- | Inheritance(継承) | ClassA <|-- ClassB |
<|.. | Realization(実現) | ClassC <|.. ClassD |
<-- | Association(関連) | ClassE <-- ClassF |
<.. | Dependency(依存) | ClassG <.. ClassH |
*-- | Composition(委譲) | ClassI *-- ClassJ |
o-- | Aggregation(集約) | ClassK o-- ClassL |
-- | Link(線) | ClassM -- ClassN |
.. | Link(破線) | ClassO .. ClassP |
その他の記述方法として下記があります。
- ラベルを付ける場合は
ClassA <-- ClassB : Label
- 関連の向きを変える場合は
ClassA --> ClassB
変数と関数
変数は下記のように記述します。
- 変数は
foo
- 型を指定する場合は
int foo
関数は下記のように記述します。
- 関数は
foo()
- 戻り値の型を指定する場合は
foo(): int
- 引数を指定する場合は
foo(bar, baz)
- 引数の型を指定する場合は
foo(int bar, String baz)
また、各記号に関しては下記の意味があります。
記号 | 意味 | サンプル |
---|---|---|
* | Abstract | foo*, foo()* |
$ | Static | foo$, foo()$ |
+ | Public | +foo, +foo() |
- | Private | -foo, -foo() |
# | Protected | #foo, #foo() |
~ | Package/Internal | ~foo |
クラスの定義
インターフェース等は下記のように記述できます。
<<interface>> ClassA
<<abstract>> ClassA
<<enumeration>> ClassA
ブロックを定義して記述することも可能です。
class ClassA {
<<interface>>
-int foo
+bar()* String
}
サンプルとDartコード
クラスの関係性をDartコードとともに示します。
コードはあくまで一例に過ぎない点に注意してください。
Inheritance(継承)
class ClassA {}
class ClassB extends ClassA {}
継承は親クラス(ClassA)の要素を子クラス(ClassB)の関係を表します。
Realization(実現)
abstract class ClassC {
void foo();
}
class ClassD extends ClassC {
void foo() => print('foo');
}
実現は抽象クラスまたはインターフェース(ClassC)と具象クラス(ClassD)の関係を表します。
Association(関連)
class ClassE {}
class ClassF {
ClassE e;
ClassF(this.e);
}
関連は"has-a"の関係を表し、矢印の向きは「誘導可能性」を示します。そのためClassFからClassEを辿ることができます。
Dependency(依存)
class ClassG {
void foo() => print('foo');
}
class ClassH {
void bar(ClassG g) {
g.foo();
}
}
依存はClassGの変更がClassHに影響を与えます。
Composition(委譲)
class ClassI {
ClassJ j = ClassJ();
}
class ClassJ {}
合成は関連のサブセットで"part-of"の関係を表し、部分(ClassJ)が唯一の全体(ClassI)に共有されます。つまり、オブジェクトの生存期間が一致します。
Aggregation(集約)
class ClassK {
ClassL l;
ClassK(this.l);
}
class ClassL {}
集約は関連のサブセットで"part-of"の関係を表し、部分(ClassF)が複数の全体(ClassE)に共有されます。つまり、オブジェクトの生存期間が一致しません。
関連と実装上の違いはないですが意味的に「全体と部分」の関係を示したものが集約と考えれます。
Link(線)
class ClassM {
ClassN n;
ClassM(this.n);
}
class ClassN {
ClassM m;
ClassN(this.m);
}
線は双方向の関連がある場合(または関連が不明の場合)を表します。
Link(破線)
class ClassO {
void foo() => print('foo');
void bar(ClassP p) {
p.bar();
}
}
class ClassP {
void bar() => print('bar');
void foo(ClassO o) {
o.foo();
}
}
破線は双方向の依存がある場合(また依存関係が不明の場合)を表します。
Discussion