类关系(UML&设计模式)
一.类之间存在的6种关系....................................................................................... 1
二.各种关系图与代码.............................................................................................. 1
1. 依赖.............................................................................................................. 1
2. 关联.............................................................................................................. 2
3. 聚合.............................................................................................................. 2
4. 组合.............................................................................................................. 3
5. 实现(接口)................................................................................................ 4
6. 继承.............................................................................................................. 6
三.总结................................................................................................................... 6
一.类之间存在的6种关系
依赖,关联,聚合,组合,实现(接口),继承(泛化)。
其中,聚合和组合是关联的两种具体关系,关联包含组合和聚合。
关系强弱:依赖是关系最弱的,关联是强依赖,聚合是强关联,组合是强聚合。
注意:继承比起接口,可以扩展,接口最好不要扩展。
二.各种关系图与代码
1. 依赖
代码:
Public class A {//注意这没有定义类B在类A中的私有变量 public B operation(B b){//返回值和方法参数 b.opb();//方法参数位置 B bb = new B();//局部变量 bb.opbb(); B.staticop();//静态方法调用 } }
|
描述:
可以简单的理解,就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、临时性的、非常弱的,但是B类的变化会影响到A;比如某人要过河,需要借用一条船,此时人与船之间的关系就是依赖;表现在代码层面,为类B作为参数被类A在某个method方法中使用。
双向关联:
C1-C2:指双方都知道对方的存在,都可以调用对方的公共属性和方法。
双向关联在代码的表现为双方都拥有对方的一个指针,当然也可以是引用或者是值。
在GOF的设计模式书上是这样描述的:虽然在分析阶段这种关系是适用的,但我们觉得它对于描述设计模式内的类关系来说显得太抽象了,因为在设计阶段关联关系必须被映射为对象引用或指针。对象引用本身就是有向的,更适合表达我们所讨论的那种关系。所以这种关系在设计的时候比较少用到,关联一般都是有向的。
单向关联:
C3->C4:表示相识关系,指C3知道C4,C3可以调用C4的公共属性和方法。没有生命期的依赖。一般是表示为一种引用。
自身关联(反身关联):
自己引用自己,带着一个自己的引用。
2. 关联
代码:
Public class A{ Private B b; } |
描述:
体现的是两个类、或者类与接口之间语义级别的一种强依赖关系,比如我和我的朋友;这种关系比依赖更强、不存在依赖关系的偶然性、关系 也不是临时性的,一般是长期性的,而且双方的关系一般是平等的、关联可以是单向、双向的;表现在代码层面,为被关联类B以类属性的形式出现在关联类A中, 也可能是关联类A引用了一个类型为被关联类B的全局变量。
3. 聚合
代码:
Public class A{ Private B b; public set(B b){ This.b=b; } } |
描述:
聚合是关联关系的一种特例,他体现的是整体与部分、拥有的关系,即has-a的关系,此时整体与部分之间是可分离的,他们可以具有各自的生命周期,部分可 以属于多个整体对象,也可以为多个整体对象共享;比如计算机与CPU、公司与员工的关系等;表现在代码层面,和关联关系是一致的,只能从语义级别来区分。
4. 组合
代码:
Public class A{ Private B b = new B(); //第一种方法; Public A(){ b=new B(); } //第二种方法; Public A(B b){ This.b=b; } //第三种方法; } |
描述:
组合也是关联关系的一种特例,他体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合;他同样体现整体与部分间的关系,但此时整体 与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束;比如你和你的大脑;表现在代码层面,和关联关系是一致的,只能从语义级别来区分。
5. 实现(接口)
代码:
Public class A{ public void op1(); public void od2(); }
public class B implements A{ public void op1(){必须实现;} public void op2(){必须实现;} public void op3(){可以扩展但不提倡;} } |
C++中接口类定义方式:
Class IPerson { public: IPerson(){}; virtual ~IPerson()=0;//注意,最好要定义此虚析构函数,能够避免其实现不能正常调用析构函数的问题 //提供给外面使用的接口一般采用纯虚函数 virtual void SetName(const string &strName)= 0; virtual const string GetName()= 0; virtual void Work()= 0; }
Class CTeacher:public IPerson { public: CTeacher(){}; virtual ~CTeacher(); string m_strName; void SetName(const string &strName); const string GetName(); void Work(); } CTeacher::SetName(const string &strName) { m_strName = name; } const string CTeacher::GetName() { return m_strName; } void CTeacher::Work() { cout <<"I am teaching!"<<endl;//老师的工作是教书,其他职业的人做的工作是不一样的。 } |
描述:
指的是一个class类实现interface接口(可以是多个)的功能;实现是类与接口之间最常见的关系;在Java中此类关系通过关键字implements明确标识,在设计时一般没有争议性;
在C++中,包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。我们可以把只能用于被继承而不能直接创建对象的类设置为抽象类(Abstract Class)。
我们把那些类中的确存在,但是在父类中无法确定具体实现的成员函数称为纯虚函数。纯虚函数是一种特殊的虚函数,它只有声明,没有具体的定义, 纯虚函数的声明有着特殊的语法格式:virtual返回值类型成员函数名(参数表)=0;
抽象类中至少存在一个纯虚函数,存在纯虚函数的类一定是抽象类,存在纯虚函数是成为抽象类的充要条件。而接口类中只能有纯虚函数。
6. 继承
代码:
Public class A{ public void op1(); public void od2(); }
public class B implements A{ public void op1(){必须实现;} public void op2(){必须实现;} public void op3(){可以扩展,提倡扩展;} ... } |
描述:
指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系;在Java中此类关系通过关键字extends明确标识,在设计时一般没有争议性;
三.总结
在Java中,应该尽量优先使用组合,而不是继承,因为继承会使得类关系过于复杂化,破坏了封装性,使用组合一样可以获得已有类的功能,而且会使新类更加稳固。
实际上,从依赖 -----〉聚合--------〉组合,类与类之间的关系更加紧密,互相之间的影响越来越大,其实我们平常比较少去区分这些关系,而且事实上这东西的定义不太好理解,所以肯定会导致认识上的偏差,所以我们使用这些东西的时候,尽量靠近大家都认同的做法,这样容易让别人理解。