目录
一.类的UML图
1.类的UML图
类封装了数据和行为,是面向对象的重要组成部分,它是具有相同属性、操作、关系的对象集合的总称。在系统中,每个类都具有一定的职责,职责指的是类要完成什么样子的功能,要承担什么样子的义务。一个类可以有多种职责,但是设计得好的类一般只有一种职责。
类图是面向对象系统建模中最常用和最重要的图,是定义其它图的基础。类图主要是用来显示系统中的类、接口以及它们之间的静态结构和关系的一种静态模型.
以下是以Hunter类为例介绍类的UML图中各个部分的具体含义和画法。
class Hunter
{
public:
int m_age = 32;
static int m_times;
string getName()
{
return m_name;
}
void setName(string name)
{
m_name = name;
}
void goHunting()
{
aiming();
shoot();
}
static void saySorry()
{
string count = to_string(m_times);
cout << "Say sorry to every animal " + count + " times!" << endl;
}
protected:
string m_name = "Jack";
void aiming()
{
cout << "使用" + m_gunName + "瞄准猎物..." << endl;
}
private:
string m_gunName = "AK-47";
void shoot()
{
cout << "使用" + m_gunName + "射击猎物..." << endl;
}
};
int Hunter::m_times = 3;
以下是Hunter类的UML图

2.类之间的关系
类之间一般有继承、关联、聚合、组合和依赖等关系,以下具体介绍这些关系的具体含义以及在UML图中的描述形式。
2.1 继承关系:
继承用于描述父子类之间的关系。在UML中,继承关系用带空心三角形的实线来表示。 关于继承关系一共有两种:普通继承关系和抽象继承关系,但是不论哪一种表示继承关系的线的样式是不变的。

2.2关联关系
关联(Assocition)关系是一种结构化的关系,表示一个对象与另一个对象之间有联系,如师傅和徒弟、班级和学生等。在UML类图中,用(带接头或不带箭头的)实线连接有关联关系的类。在C++中这种关联关系在类中是这样体现的,通常将一个类的对象作为另一个类的成员变量。
类之间的关联关系有三种,分别是:单向关联、双向关联、自关联。
2.2.1单项关联

2.2.2双向关联

2.2.3自关联

2.3聚合关系
聚合(Aggregation)关系表示整体与部分的关系。在聚合关系中,成员对象是整体的一部分,但是成员对象可以脱离整体对象独立存在。在UML中,聚合关系用带空心菱形的直线表示,下面举两个聚合关系的例子:
- 汽车(Car)与 引擎(Engine)、轮胎(Wheel)、车灯(Light)
- 森林(Forest)与 植物(Plant)、动物(Animal)、水(Water)、阳光(Sunshine)


2.4组合模式
组合(Composition)关系也表示的是一种整体和部分的关系,但是在组合关系中整体对象可以控制成员对象的生命周期,一旦整体对象不存在,成员对象也不存在,整体对象和成员对象之间具有同生共死的关系。 在UML中组合关系用带实心菱形的直线表示,下面举两个组合关系的例子: 头(Head)和 嘴巴(Mouth)、鼻子(Nose)、耳朵(Ear)、眼睛(Eye) 树(Tree)和 树根(Root)、树干(Trunk)、树枝(Branch)、树叶(Leaf)


2.5依赖关系
依赖(Dependency)关系是一种使用关系,特定事物的改变有可能会影响到使用该事物的其他事物,在需要表示一个事物使用另一个事物时使用依赖关系,大多数情况下依赖关系体现在某个类的方法使用另一个类的对象作为参数。 在UML中,依赖关系用带箭头的虚线表示,由依赖的一方指向被依赖的一方。



二、设计三原则
我们在进行程序设计的时候,要尽可能地保证程序的可扩展性、可维护性和可读性,所以需要使用一些设计模式,这些设计模式都遵循了以下三个原则:单一职责原则、开放封闭原则和依赖倒置原则。
2.1单一职责原则
C++面向对象三大特性之一的封装指的就是将单一事物抽象出来组合成一个类,所以我们在设计类的时候每个类中处理的是单一事物而不是某些事物的集合。 设计模式中所谓的单一职责原则,就是对一个类而言,应该仅有一个引起它变化的原因,其实就是将这个类所承担的职责单一化。
如果一个类承担的职责过多,就等于把这些职责耦合到了一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致设计变得脆弱,当变化发生时,设计会遭受到意想不到的破坏。由此可见,让一个类承担太多的职责绝非好事。 软件设计真正要做的事情就是,根据需求发现职责,并把这些职责进行分离,添加新的类,给当前类减负,越是这样项目才越容易维护。
2.2开放封闭原则
开放 – 封闭原则说的是软件实体(类、模块、函数等)可以扩展,但是不可以修改。也就是说对于扩展是开放的,对于修改是封闭的。
该原则是程序设计的一种理想模式,在很多情况下无法做到完全的封闭。但是作为设计人员,应该能够对自己设计的模块在哪些位置产生何种变化清楚,因此需要在需要变化的位置创建抽象类来隔离以后发生的这些同类变化(应用多态创建新的子类并重写父类虚函数,用以更新处理动作)。
2.3依赖倒转原则
关于依赖倒转原则,有以下两条描述:
1 高层模块不应该依赖低层模块,两个都应该依赖抽象。
2 抽象不应该依赖细节,细节应该依赖抽象。
- 高层模块:可以理解为上层应用,就是业务层的实现 。
- 低层模块:可以理解为底层接口,比如封装好的API、动态库等 。
- 抽象:指的就是抽象类或者接口,在C++中没有接口,只有抽象类。
以下例子为例说明:
项目组接了一个新项目,低层使用的是PostgreSql的数据库接口,高层基于这套接口对数据库表进行了接口封装,实现了对业务层数据的处理。而后由于某些原因,需要更换Oracle数据库,由于低层的数据库接口变了,高层代码的数据库操作部分是直接调用了低层的接口,因此也需要进行对应的修改,无法实现对高层代码的直接复用。
基于依赖倒转原则将项目的结构换成下图的这种模式之后,低层模块发生变化,对应高层模块是没有任何影响的,这样程序猿的工作量降低了,代码也更容易维护

里氏代换原则 :所谓的里氏代换原则就是子类类型必须能够替换掉它们的父类类型。关于这个原理的应用其实也很常见,比如在Qt中,所有窗口类型的类的构造函数都有一个QWidget*类型的参数(QWidget 类是所有窗口的基类),通过这个参数指定当前窗口的父对象。虽然参数是窗口类的基类类型,但是我们在给其指定实参的大多数时候,指定的都是子类的对象,其实也就是相当于使用子类类型替换掉了它们的父类类型。
这个原则的要满足的第一个条件就是继承,其次还要求子类继承的所有父类的属性和方法对于子类来说都是合理的。
比如我们创建了父类A,那么它们是可以继这个类A实现子类B,在实际应用中就可以使用子类B替换掉父类A,同时功能也不会受到影响,父类实现了复用,子类也能在父类的基础上增加新的行为,这个就是里氏代换原则。
1761

被折叠的 条评论
为什么被折叠?



