用 C++ 示例解释 UML 类图
当一个类是其他类的集合或容器,但容器中包含的类对容器没有很强的生命周期依赖时,就会发生聚合——本质上,如果容器被销毁,它的内容不会被销毁。当一个类是其他类的集合或容器,但容器中包含的类对容器具有很强的生命周期依赖性时,可能会发生组合——本质上,如果容器被销毁,其内容也会被销毁。可以看到,下面的Object类,就是一个自身关联的应用,它有一个自己指向自己的指针,用来实现链表。如您所知,类图是显示系统
如您所知,类图是显示系统中不同类的属性、操作以及不同对象之间关系的图。
即使我已经使用它很长时间了; 每次使用的时候总是很混乱。 这篇文章就是为像我这样的人准备的; 对初学者也有帮助,这里我将用C++类示例解释类图。
类表示
class Circle
{
private:
double radius;
Point center;
public:
setRadius(double radius);
setCenter(Point center);
double getArea();
double getCircumfrence();
};
上述类的类图如下所示。
类的不同可见性可以表示为
“+” Public
“-” Private
“#” Protected
不同的参数方向
“in”参数是一个输入参数。
“Inout” 该参数既可以输入也可以输出。
“Out” 该参数是一个输出参数。
类中不同类型的成员
1) 静态成员用下划线表示。
2) 纯虚函数用斜体表示。
类关系
在一个系统中,一个类可能与不同的类相关,以下是不同的关系。
- 关联(Association)(知道一个)
- 依赖(Dependency)(使用一个)
- 聚合(Aggregation)(有一个)
- 组合(Composition )(有一个)
- 继承(Inheritance)(是一个)
- 类模板(Class template)
关系中的不同多重性
“0..1” 没有实例,或一个实例(可选)
“1” 正好一个实例
“0..* or *” 零个或多个实例
“1..*” 一个或多个实例(至少一个)
关联(Association)
一个类知道另一个类; 一个类包含指向另一个类对象的指针或引用。
关联可以分为单向关联、双向关联、自身关联。
1)单向关联
单向关联X->Y:表示X“知道”Y,X可以调用Y的公共属性和方法。没有生命周期的依赖。
表示
C++ 示例
class X
{
public:
Y *pY;
};
class Y
{
};
这里“X”类中的“Y *pY”没有任何生命周期依赖(组合),也没有暗示任何包含(聚合); 所以它是一个关联。
2)双向关联
双向关联X-Y:双方都“知道”对方,都可以调用对方的公共属性和方法。
表示
C++ 示例
class X
{
public:
Y* pY;
};
class Y
{
public:
X* pX;
};
3)自身关联
自身关联:自己引用自己,这个在链表中非常常见。
可以看到,下面的Object类,就是一个自身关联的应用,它有一个自己指向自己的指针,用来实现链表。
表示
C++ 示例
class Object
{
public:
int data;
Object *next;
};
class ObjectList
{
public:
Object *first;
ObjectList();
void insert(Object* obj);
void print() const;
};
依赖(Dependency)
依赖用来表述一个类X“use”了另一个类Y。X可以是通过任何方式“use”类Y,如:
1)X的成员函数的返回值为Y;
2)X的成员函数使用Y作为函数参数;
3)X的成员函数的内部实现使用了Y;
表示
依赖关系通常使用虚线箭头“---->”表示,箭头指向被“use”的类。
C++示例
class X
{
...
Y f0() {…; return y; }
void f1(Y y) {…; y.Foo(); }
void f2(Y *y) {…; y->Foo(); }
void f3(Y &y) {…; y.Foo(); }
void f4() { Y y; y.Foo(); …}
void f5() {…; Y::StaticFoo(); }
...
};
聚合(Aggregation)
当一个类是其他类的集合或容器,但容器中包含的类对容器没有很强的生命周期依赖时,就会发生聚合——本质上,如果容器被销毁,它的内容不会被销毁。 您可能会混淆聚合和关联。关联与聚合的不同之处仅在于关联不表示任何包含关系。
表示
Window类包含其Shape的列表,Shape也可能被其他类共享;Shape的生命周期不取决于Window类。
C++示例
class Window
{
public:
//...
private:
vector<Shape> itsShapes;
};
组合(Composition )
组合是更强的聚合形式。 当一个类是其他类的集合或容器,但容器中包含的类对容器具有很强的生命周期依赖性时,可能会发生组合——本质上,如果容器被销毁,其内容也会被销毁。
表示
C++ 示例
class Point
{
};
class Circle
{
private:
...
Point center;
....
};
class X {
...
Y a; // 1; Composition
Y b[10]; // 0..10; Composition
};
class X {
X() { a = new Y[10]; }
~X(){ delete [] a; }
...
Y *a; // 0..10; Composition
};
class X {
...
vector<Y> a; // if X contains vector, it is a composition;
};
class X {
...
vector<Y*> a; // if X contains vector, and construction and destruction of Y* happen
// inside X (in constructor/destructor) it is composition; otherwise
// aggregation.
};
继承(Inheritance )/泛化(Generalization)
在继承关系中,一个类是从另一个类派生的。 这是两个类之间的“是一个”关系。
表示
这里Shape是一个抽象类,这就是它以斜体显示的原因。 Shape类的Draw()和Erase()方法是纯虚函数,所以也用斜体表示。
C++示例
class Shape
{
public:
virtual void Draw() = 0;
virtual void Erase() = 0;
};
class Circle : public Shape
{
};
class Ellipse : public Shape
{
};
类模板
模板类是泛型类。C++、java、C#等语言都支持泛型编程。
表示
C++ 表示
template
class X {
...
...
...
};
X Y
...
X a;
...
template <typename Key, typename T>
calss MyMap
{
public:
MyMap()
{
}
virtual ~MyMap()
{
}
};
typedef MyMap<int, Person*> PersonMap;
参考链接:EA画UML图中如何创建类模板
// 简单的一个C++代码,实现数组的建立,以及给数组第一个元素赋初值和得到数组第一个元素的值
#include <iostream>
using namespace std;
template <typename T, int size>
class Array
{
private:
T elements[size];
public:
void addElement(T e)
{
elements[0] = e;
}
T getElement(int i)
{
return elements[i];
}
};
using IntArray = Array<int, 20>;
using FloatArray = Array<float, 10>;
using CharArray = Array<char, 30>;
int main()
{
IntArray array_int;
array_int.addElement(3);
cout << array_int.getElement(0) << endl;
FloatArray array_float;
array_float.addElement(3.5);
cout << array_float.getElement(0) << endl;
CharArray array_char;
array_char.addElement('4');
cout << array_char.getElement(0) << endl;
return 0;
}
运行结果:
扩展阅读:UML—模板类实现
翻译原文:UML Class Diagram Explained With C++ samples
参考文章:C++ UML小结
UML学习:统一建模语言(UML)学习指南
visio绘制UML:
UML软件:免费在线流程图思维导图
更多推荐
所有评论(0)