面向对象设计主要使用UML的类图,它是一种图形化工具,用于描述系统中所包含的类以及它们之间的相互关系。类图有助于简化对系统的理解,是系统分析和设计阶段的重要产物,同时也为系统编码和测试提供了重要的模型依据。

一、UML类图简介

统一建模语言(UML)类图是一种用于描述系统结构的图形化工具。它以类和对象为基础,主要用于表示系统中的类、接口、继承关系、关联关系等元素,以及它们之间的静态结构和关系。本文将深入介绍UML类图的基本元素、关系类型以及如何创建一个简单而有效的类图。

类图的主要作用是对系统的词汇进行建模、对简单的协作进行建模和对逻辑数据库模式进行建模。它描述了软件系统的结构,是一种静态建模方法。类图用来描述系统中有意义的概念,包括具体的概念、抽象的概念、实现方面的概念等,是对现实世界中事物的抽象。类图的主要作用是对系统的词汇进行建模、对简单的协作进行建模和对逻辑数据库模式进行建模。类图显示集合的类,接口,关联,协作和约束,它也被称为作为结构图。

UML类图是在设计程序之前画的,而不是等写完程序再画!在Java中有接口,而在C++中没有接口,只有抽象类。

二、类的UML画法

可以使用工具Visio或者processon在线作图来绘制UML类图。以下是一个关于猎人类的类图示例:

```

+----------------+ +----------------+ +---------------------+ +-------------------+ +------------------------+

| Person | | Animal | | Hunt | | HuntResult | | Person |

+----------------+ +----------------+ +---------------------+ +-------------------+ +------------------------+

| name | | name | | purpose() | | result | | _name |

| age | | age | | (return type) | | (return type) | | _age |

| gender | | gender | | | | | | _gender |

| ... | | ... | | | | | | ... |

+----------------+ +----------------+ +---------------------+ +-------------------+ +------------------------+

```

在这个示例中,我们定义了一个名为Person的类,它与Animal类存在继承关系。Person类具有name、age、gender等属性以及purpose()和result()等操作方法。Hunt类表示猎杀行为,其目的是捕获动物。HuntResult类表示猎杀结果。通过这个类图,我们可以清晰地了解到系统中各个类之间的关系和属性。

类图如下:

```

+----------------+

| Hunter |

+----------------+

| -m_age: int |

| -m_times: static int|

| m_name: string |

+----------------+

| goHunting(): void |

+----------------+

| aim(): void |

| shoot(): void |

| saySorry(): void |

+----------------+

| getName(): string |

+----------------+

```

在UML类图中,可见性有以下几种:public、private、protected和default。其中,public表示当前类、当前包、子孙类和其他包;protected表示当前类、当前包和子孙类;default表示无,只有当前类和当前包可以访问。

方法名称后面的括号中包含参数名和参数类型,返回值类型用冒号表示。如果一个类中有纯虚函数,那么在画UML类图时,类名需要使用斜体显示,并且如果是纯虚函数则需要在最后给函数指定=0。

在UML中的关系是面向对象关系。继承关系指向子类,被指向方为父类;实现接口的实现关系指向实现类,被指向方为接口类;整体和部分关系指向整体类,被指向方为部分类;聚合整体和部分关系指向整体类,被指向方为部分类;关联是类与类之间的联结,将一个类的对象作为另一个类的属性;依赖是使用关系,指向方使用类,被指向方为被使用类。继承(泛化)关系有两种:普通继承关系和抽象继承关系。不论哪一种表示继承关系的线的样式是不变的。

```cpp

#include #include

using namespace std;

class Bird {

public:

string getName() {

return m_name;

}

void setName(string name) {

m_name = name;

}

virtual void fly() {}

virtual void eat() {}

protected: // 可以被子类继承

string m_name;

};

class Parrot : public Bird {

public:

void fly() override {

cout << "我拍打翅膀飞行..." << endl;

}

void eat() override {

cout << "我喜欢吃肉肉的小虫子..." << endl;

}

};

class Eagle : public Bird {

public:

void fly() override {

cout << "我展翅翱翔..." << endl;

}

void eat() override {

cout << "我喜欢吃小动物..." << endl;

}

};

```

```cpp

class Root { };

class Trunk { };

class Branch { };

class Leaf { };

class Tree {

public:

Tree() {

m_root = new Root;

m_trunk = new Trunk;

m_branch = new Branch;

m_leaf = new Leaf;

}

~Tree() {

delete m_root;

delete m_trunk;

delete m_branch;

delete m_leaf;

}

private:

Root* m_root;

Trunk* m_trunk;

Branch* m_branch;

Leaf* m_leaf;

};

```

```cpp

class Plant { // 植物 };

class Animal { // 动物 };

class Water { // 水 };

class Sunshine { // 阳光 };

// 森林类

class Forest {

public:

Forest(Plant p, Animal a, Water w, Sunshine s) : m_plant(p), m_animal(a), m_water(w), m_sun(s) {}

private:

Plant m_plant;

Animal m_animal;

Water m_water;

Sunshine m_sun;

};

```

在UML中,单向链表和双向链表的表示方法如下:

1. 单向链表:在UML类图中,单向链表通常使用带箭头的实线来表示。箭头从链表的头部指向尾部,表示节点之间的自关联关系。例如,对于双向链表节点类Node,其C++写法为:

```cpp

class Node {

private:

int m_data = 0;

Node* m_prev;

Node* m_next;

};

```

对应的UML类图应当是:

- 一般使用带箭头的实线来描述自关联关系,即我中有我,独角戏。

- 有些UML绘图软件表示类与类的关联关系时,使用的就是一条实线,没有箭头。

2. 双向链表:在UML中,双向链表同样使用带箭头的实线来表示。箭头从链表的头部指向尾部,表示节点之间的自关联关系。例如,对于双向链表节点类Node,其C++写法为:

```cpp

class Node {

private:

int m_data = 0;

Node* m_prev;

Node* m_next;

};

```

对应的UML类图应当是:

- 一般使用带箭头的实线来描述自关联关系,即我中有我,独角戏。

- 有些UML绘图软件表示类与类的关联关系时,使用的就是一条实线,没有箭头。

在创建UML类图时,我们需要考虑组合、聚合和关联这三种关系。以下是重构后的段落结构:

1. 组合关系:

在创建之后,创建的关系需要在组合对象销毁之前销毁。被组合对象不能脱离组合对象独立存在,而且也只能属于一个组合对象。实际应用中,这三种关系的界限划分其实没有那么清楚,有些时候我们会感觉组合和聚合没什么区别,所以,在设计的时候没必要死抠细节,只要能够利用对象之间的关系设计出可行的解决方案即可。如果同时有多个关系,只需画出最强的关系即可。

2. 聚合关系:

聚合关系与组合关系的区别主要在于语义上:关联的两个对象之间一般是平等的,而聚合则一般是不平等的。例如,人和自己的心脏属于组合关系,因为心脏不能脱离人体而独自存在;图书馆看书的时候,人和书属于聚合关系,因为书是可以独立存在的,而且书不仅可以属于自己,也可以属于别人;朋友之间属于关联关系,因为这种关系是平等的,关联关系只是用于表示两个对象之间的一种简单的联系而已。

3. 关联关系:

最后,再举例子来描述一下这三种关系:人和自己的心脏属于组合关系;图书馆看书的时候,人和书属于聚合关系;朋友之间属于关联关系。使用右上角的带三角折痕的矩形加虚线来表示注释。参考自:https://subingwen.cn/design-patterns/UML-class-diagrams/。注:仅供学习参考,如有不足,欢迎指正!