第1章 UML基础:类的关系
来源:互联网 发布:山东省软件评测中心 编辑:程序博客网 时间:2024/05/18 10:34
前前后后犹豫好久,到底是写不写设计模式,毕竟自己不是科班出身,最后还是决定根据大神博客和设计模式之禅写下几种常见的
设计模式,等到后面使用的时候再来复习。不管是跟着什么资料在学习,记住一定要思考,一定要敲代码,一定要升华!!!
1、类的关系
1.1、继承(is-a)和实现:继承表示父子关系(子类是特殊的父类),实现有点像接口继承。
1.2、依赖(use-a):表示一个类要使用(use)另一个类。
(1)、类图
表示C21要使用C22类型
(2)、三种依赖方式:函数参数或返回值、局部变量和静态成员函数或变量
class C21{public: //1、使用函数形参和返回值发生依赖关系 C22 test(C22 theC22); //2、使用局部变量发生依赖关系 void test() { C22 theC22; //或C22* theC22 = new C22; //离开这个作用域后the22要销毁 } //3、全局变量或静态变量(函数)发生依赖关系 void test() { C22 theC22 = g_C22; //g_C22为全局变量 C22::func(); //使用类的静态成员函数 }};
1.3、关联:是一种平等的、朋友关系。
(1)、双向关联:双方都知道对方的存在,可以使用对方的公有成员变量和函数。
理解:资源在外部,C31类型 表示的是指向资源的指针。
a、代码表现:双方拥有对方的一个指针或引用。
b、之所以是指针有原因。如果是值(对象)那么就不是关联。因为是值的话,C31对象消失C32对象也会跟着消失。(站在内存的角
度理解,资源分配在哪里)。 组合:整体与部分的关系,而且整体消息部分也会消息,部分不能独立于整体。
(2)、单向关联
注意依赖和单向关联
a、表示相识关系,指C33知道C34,可以调用C34的公共成员变量和函数
b、代码上表示为C33有C34的指针,而C34对C33一无所知。
(3)、自身关联:自己的内部有一个指向自身的指针或引用
1.4、聚合与组合
(1) 聚合:(has-a),表示整体-部分的关系,但部分可以脱离整体而单独存在。
关联是平等的朋友关系。 聚合:整体和部分的关系
a、如C41聚合C42,但是C42可以离开C41而独立存在。在创建C41类的对象时,一般不会马上创建C42对象,而是等待一个外界的
对象传给它。 资源在外部。
b、当用C++代码来描绘关联和聚合时,都是一个类包含了另外一个类的指针。但是他们是有区别的,这个区别不是C++语法上的差
别,而是语义上的差别。聚合是整体和部分的关系,而且关联是平等的朋友关系,比如。张三和李四,是关联。而张三和张三的杯
子是聚合。张三和张三的鼻子是组合。
(2)、组合(contains-a):表示整体部分关系,但是部分不能脱离整体单独存在。 如:手脚是身体的一部分,轮子与汽车。
a、组合用的是值对象(外部传入的,生命周期与整体一样)
b、聚合是指针。但有时组合也可以用指针,在构造函数中创建对象,析构函数中销毁对象。
区别:聚合,一般其对象指针是由类外传入的,而组合是在类内部的构造函数中new出来的。
c、从语义上看,组合与聚合也是不一样的。当表示聚合时,部分可以脱离整体。而组合不行。
2、依赖和聚合/组合、关联的区别
(1)、聚合与组合
a、聚合与组合都是一种整体和部分的关系。(脱离能不能存在)
b、部件的生命周期不同
聚合关系中,整件不会拥有部件的生命周期,所以整件删除时,部件不会被删除。再者,多个整件可以共享同一个部件。
组合关系中,整件拥有部件的生命周期,所以整件删除时,部件一定会跟着删除。而且,多个整件不可以同时间共享同一个部件。
c、聚合关系是“has-a”关系,组合关系是“contains-a”关系。
(2)关联和聚合
a、表现在代码层面,和关联关系是一致的,只能从语义级别来区分。
b、关联和聚合的区别主要在语义上,关联的两个对象之间一般是平等的,例如你是我的朋友,聚合则一般不是平等的。
c、关联是一种结构化的关系,指一种对象和另一种对象有联系。
d、关联和聚合是视问题域而定的,例如在关心汽车的领域里,轮胎是一定要组合在汽车类中的,因为它离开了汽车就没有意义
了。但是在卖轮胎的店铺业务里,就算轮胎离开了汽车,它也是有意义的,这就可以用聚合了。
(3)、关联和依赖
a、关联关系中,体现的是两个类、或者类与接口之间语义级别的一种强依赖关系,比如我和我的朋友;这种关系比依赖更强、不
存在依赖关系的偶然性、关系也不是临时性的,一般是长期性的,而且双方的关系一般是平等的。
b、依赖关系中,可以简单的理解,就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、临时性的、非常弱的,但
是B类的变化会影响到A。
(4)、注意:
上述的几种关系(依赖、关联、聚合/组合)在代码中可能以指针、引用、值等的方式在另一个类中出现,不拘于形式,只有配合
语义,结合上下文来判断。而只给出一段代码让我们来判断是什么关系,还是无法准确判断的。
(5)、所谓的这些关系只是在某个问题域才有效,离开了这个问题域,可能这些关系就不成立了。
这几种关系都是语义级别的,所以从代码层面并不能完全区分各种关系。
总的来说关系的强弱程度:组合>聚合>关联>依赖
3、类关系实例分析
(1)、类图
(2)、代码实现
//Cgprs.h和Cgprs.c
#ifndef __CGPSReceiver_H__#define __CGPSReceiver_H__class Cgprs{public:void navigate(void);};#endif#include "Cgprs.h"#include <iostream>using namespace std;void Cgprs::navigate(void){cout << "开始使用GPRS导航..." << endl;}//CEngine.c和CEngine.h
#ifndef __CENGINE_H__#define __CENGINE_H__class CEngine{private:int mCapacity;int mPower;public:CEngine(int capacity, int power);~CEngine();void start();void stop();int getCapacity() const; //不能修改成员变量的值void setCapacity(int capacity);int getPower() const;void setPower(int power);};#endif#include "CEngine.h"#include <iostream>using namespace std;//尽量使用初始化列表成员变量初始化CEngine::CEngine(int capacity, int power) : mCapacity(capacity), mPower(power){}CEngine::~CEngine(){}void CEngine::start(){cout << mCapacity << "cc,";cout << mPower << "马力的发动机发动了!\n" << endl;}void CEngine::stop(){cout << "发动机关闭了!\n" << endl;}int CEngine::getCapacity() const{return mCapacity;}void CEngine::setCapacity(int capacity){mCapacity = capacity;}int CEngine::getPower() const{return mPower;}void CEngine::setPower(int power){mPower = power;}
//CWheel.c和h文件
#ifndef __CWHEEL_H__#define __CWHEEL_H__#include <string>using namespace std;class CWheel{private:int mNo; //数量int mSize; //尺寸string mTypeName; //类型void check(); //出场检查public:CWheel();CWheel(int no, int size, string TypeName); //构造函数CWheel(const CWheel& cw); //拷贝构造函数CWheel& operator= (const CWheel& cw); //赋值构造函数};#endif#include "CWheel.h"#include <iostream>using namespace std;CWheel::CWheel(){}CWheel::CWheel(int no, int size, string TypeName) : mNo(no), mSize(size), mTypeName(TypeName){check();}CWheel::CWheel(const CWheel& cw){mNo = cw.mNo;mTypeName = cw.mTypeName;mSize = cw.mSize;}CWheel& CWheel::operator= (const CWheel& cw){if (this == &cw) return *this;mNo = cw.mNo;mTypeName = cw.mTypeName;mSize = cw.mSize;return *this;}void CWheel::check(){cout << "检查第" << mNo + 1 << "个车轮:型号(" << mTypeName << "),";cout << "大小(" << mSize << ")" << endl;}//CVehicle.c和.h
#ifndef __CVEHICLE_H__#define __CVEHICLE_H__#include <string>#include "CWheel.h"using namespace std;//交通工具类可以实现为接口,抽象类class CVehicle{protected:string mColor;string mMake;int mTopSpeed;CWheel mWheel; //车轮与CVehicle是组合关系,声明为值对象public:CVehicle();void speedup();void slowdown();void start();void stop();};#endif#include "CVehicle.h"#include <iostream>using namespace std;CVehicle::CVehicle(){}void CVehicle::speedup(){cout << "正在加速..." << endl;}void CVehicle::slowdown(){cout << "正在减速..." << endl;}void CVehicle::start(){cout << "车子开始启动..." << endl;}void CVehicle::stop(){cout << "车子停下..." << endl;}//CCar.c和.h文件
#ifndef __CCAR_H__#define __CCAR_H__#include "CEngine.h"#include "Cgprs.h"#include "CVehicle.h"class CCar : public CVehicle{protected:CEngine mEngine; //发动机与CCar类是组合关系,声明为值关系Cgprs* mGPSReceiver; //导航与CCar是聚合关系,声明为指针,由外部传入public:CCar(string color, string make, int speed, Cgprs* gps);~CCar();void drive();};#endif#include "CCar.h"#include <iostream>using namespace std;CCar::CCar(string color, string make, int speed, Cgprs* gps) : mEngine(0, 0){mColor = color;mMake = make;mTopSpeed = speed;mEngine.setCapacity(mTopSpeed + 1000);mEngine.setPower(mTopSpeed - 70);cout << mColor << mMake << "车,最高时速:" << mTopSpeed << endl;mGPSReceiver = gps;mWheel = CWheel(1, 36, "A型汽车车轮");}CCar::~CCar(){}void CCar::drive(){if (mGPSReceiver){mGPSReceiver->navigate();}mEngine.start();speedup();cout << "汽车行驶中..." << endl;slowdown();mEngine.stop();stop();}
//CBicycle.h和.c
#ifndef __CBICYCLE_H__#define __CBICYCLE_H__#include "CVehicle.h"using namespace std;class CBicycle : public CVehicle{public:CBicycle();~CBicycle();void ride();};#endif#include "CBicycle.h"#include <iostream>using namespace std;CBicycle::CBicycle() : CVehicle(){mColor = "白色";mMake = "永久";mTopSpeed = 20;cout << mColor << mMake << "自行车,最高时速:" << mTopSpeed << endl;mWheel = CWheel(1, 21, "B型自行车车轮"); //赋值构造函数 赋值式 调用构造函数临时对象//mWheel(CWheel(1, 21, "B型自行车车轮")); //拷贝构造 定义式}CBicycle::~CBicycle(){}void CBicycle::ride(){start();speedup();cout << "自行车行驶中..." << endl;slowdown();stop();}//CPerson.c和.h
#ifndef _CPERSON_H_#define _CPERSON_H_#include "Cgprs.h"#include "CBicycle.h"#include "CCar.h"class CPerson{public:Cgprs *mGPSReceiver; //CGPSReceiver与CPerosn是关联关系(平等、朋友关系),由类外传入void drive(CCar* car); //CCar与CPerson通过形参发生依赖关系void ride(CBicycle* bicle); //CBicycle与CPerson通过形参发生依赖关系void use(Cgprs* gps); //将gps传给mGPSReceiver};#endif #include "CPerson.h"void CPerson::drive(CCar* car){car->drive();}void CPerson::ride(CBicycle* bicycle){bicycle->ride();}void CPerson::use(Cgprs* gps){mGPSReceiver = gps;mGPSReceiver->navigate();}//main.c
#include <iostream>#include "CPerson.h"using namespace std;int main(void){CPerson person;//GPSCgprs gps;//cout << (void*)(&gps) << endl;//开车CCar* car = new CCar("黑色", "红旗", 200, &gps);person.drive(car);delete car;printf("\n");//骑自行车CBicycle *bicycle = new CBicycle();person.ride(bicycle);delete bicycle;printf("\n");//测试GPSperson.use(&gps);cin.get();return 0;}
程序测试结果:
写程序的过程中注意几点:
1、注意根据类图定义类的顺序
2、阶段性编译原则
总结:继承 实现(抽象类、接口定义) 依赖(use-a) 关联:语义上是平等的朋友关系
聚合(has-a):整体-部分关系,部分可以脱离整体存在 组合(contain-a):整体-部分关系,部分不能脱离整体。
特定的类之间的关系,在代码层面上可能相同,但是可以在语义上进行区分。所以类之间的关系,需要在特定的环境下进行区分类之间的关系。
通过上面的例子可以更好的了解类之间的关系,有助于进一步理清后面思路。
- 第1章 UML基础:类的关系
- UML类的关系
- UML基础以及关系的形象解读
- UML最基础的几种关系
- UML基础(一)——UML中的类(接口)以及类关系的表示方法
- UML基础(二)——UML中的类(接口)以及类关系的表示方法
- UML基础(一)——UML中的类(接口)以及类关系的表示方法
- UML基础(二)——UML中的类(接口)以及类关系的表示方法
- UML类间的关系
- UML类之间的关系
- UML类之间的关系
- UML表示类的关系
- UML------类的关系图
- UML类之间的关系
- UML的类图关系
- UML类图的关系
- UML类间的关系
- UML ,类的关系解析
- 配置SQL SERVER远程连接以及kettle连接SQL SERVER
- Java递归-实现阶乘;斐波拉契数列;删除文件夹的文件
- 如何在xib/storyboard中设置视图的属性,如圆角?
- DB9和DB25的常用信号脚说明;RS232接口针脚定义
- 接口安全性解析
- 第1章 UML基础:类的关系
- Jquery validate使用小结
- apache和tomcat有什么不同,为什么要整合apache 和tomcat? ----- 百度知道
- CBB电容的特点和原理用途
- Apache、Tomcat与Catalina作为软件名字的含义与关系
- 设计模式之工厂模式
- 【慕课网Spring系列学习攻略】IOC及Bean容器篇
- OKHTTP学习之基础知识及运用
- Canvas 画布的属性