前言:这六种关系里:泛化=实现>组合>聚合>关联>依赖;其中组合-聚合-关联这三个如果只是给出一段代码是无法判断具体是什么关系的,需要配合语义或说业务场景来能进行区分(和设计模式一样可能存在又像A关系又像B关系的情况);
一:泛化
泛化是一种抽象和具体或说一般和特殊的关系,在java里用extends关键字表示,它指定了子类怎样特化父类的特征和行为,这里特征可以理解为实例属性,而行为则可以理解为实例方法;
如人是抽象类,而中国人是一个更加具体的类,中国人 extends 人;那么在人这个类里的国籍这个属性就可以在中国人这个之类里特化其值为中国,而人里的说话这个行为则可以在中国人里特化为说中国话;
二:实现
实现是类和接口之间的关系,表示某个类具有接口中声明的全部行为,在java里用implements关键字表示;注意,在编程语言里接口除了是提供方法集合还可以提供类似注解一样的特性,如Serializable接口,它内部
没有声明任何的方法,但是如果类没有实现此接口在某些序列化时会抛异常(其实就是这些序列化的api内部会判断是否instanceof Serializable,不是则抛异常,而不是说真的非得实现这个类才能序列化)
三:组合
组合是仅次于上面两个的关系的,它代表部分和整体的关系,如手和人的关系,人不存在了自然手也就不存在了(注意这个是实例层面上的关系,而不是说类上面的,它是指具体的人不存在了,自然那只属于这个人的具体的手也就不存在了),在SpringMVC源码里存在HandlerMethod对象,这个对象用于描述一个方法,因此在这个对象内部还存在多个MethodArgument成员用于描述这个方法的参数,那么这里面HandlerMethod和MethodArgument之间就是组合关系;这里有个很大的特点就是每个MethodArgument对象只属于某个HandlerMethod而不能在其它地方进行复用;组合关系是成员级别的依赖;还有个典型的就是状态模式里的状态对象就是以组合的关系存在于其Context类里;
四:聚合
聚合是次于组合的一种关系,它表示的是是一个对象拥有另一个对象的关系(也是部分-整体,关联则不是),其也是以成员的形式存在于类里;比如笔记本和其显示屏,当这个笔记本要报废了,我们可以将还有用的显示屏拆卸下来;
这里n是1,但是关系上是可以1-n的,比如跑车和*就可以是1-4;
五:关联
关联又是次于聚合的关系,它也是以成员的形式存在与类中,但是一般强调的是关系而不是部分-整体(这里有迷惑性,比如多个部门都可以使用某台打印机,但这台打印机是不属于某个部门的,虽然看起来打印机和部门的关系似乎是部分-整体即聚合关系,但这种情况应该理解为关联);而且关联是可以n-n的;用学生和老师是比较好理解关联关系的;
六:依赖
依赖是耦合性最低的关系了,它一般是类中方法里的参数类型、局部变量、对类静态方法或属性的引用;
七:总结
1.以个人目前的理解 解释下为什么泛化=实现>组合>聚合>关联>依赖;要解释下面的概念不能只用类与类之间的关系,更应该是类对象与类对象之间的关系(假设万物皆类),或者说通过实例与实例来衍生出对应类与类之间的关系;
注意,不要钻牛角尖,比如静态方法、静态属性,因为静态方法和静态属性也可以理解为实例方法和实例属性,特别是对于Java而言,静态方法就是其类的Class对象的实例方法(可以通过反射测试下就知道了)
1)泛化:A类 extends B类,那么在我实例化A之前A就已经具备了B的特性和行为;(A可以对B的特征明确化如有默认值,和对B的行为有复写或实现)
2)实现:A类 implements C接口,显然在我实例化A之前A肯定已经是实现了C的接口;(注意不要钻牛角尖比如说如果A是抽象类之类的,即便A是抽象类如果有Z类是实例类且继承了A那么实例化Z就会实例化A)
3)组合:D类以组合的关系成为A类的组件,那么D类在A类里一定是以成员存在的而非参数之类的,故D类对象在A对象里是可以存在于整个A的生命周期的(但服从A的管理也可能提早销毁),而且最终要的一点也是区别
于聚合及关联的一点是,某个D对象就是属于某个A对象(是1-n的对应关系),它不能像策略模式一样某个策略对象可以复用到其它对象里;(可以存在多个D类对象,但是每个D类对象都只属于一个A类对象,且其生命周期由A管理)
4)聚合:和组合的区别在于,E类以聚合的关系成为A类的组件(注意仍然是成员级别的关系),但是E类对象可以不只是属于某个A类对象,它还可以是M类对象的组件(即E对象可以同时依附于多种类对象),而且此E类对象的生命周期也不该由A或M类管理;
比如Jedis对象内部的网络模块就是以组合的关系存在于某个Jedis对象里,当某Jedis对象废弃了其内部的网络模块可以用于另一个Jedis对象,注意,聚合模式也是1-n的对应关系;
5)关联:关联也是成员级别的关系(即具有长期性的特点而不是说执行完某个方法某对象就消失了),和聚合的区别在于关联关系是可以n-n的关系;而且在语义上和聚合也不一样,虽然聚合里A和E类的对象可以单独存在,但是E仍然是组件
一样的东西;比如A和F类以关联关系存在,那么A和F是平等的,不存在说谁依附于谁;现实生活中学生和老师的个体就是一种关联关系,某个学生可以有多个老师,而某个老师也可以有多个学生;在代码层面就是Student类内部有成员Teacher数组,而Teacher内部也可以有Student数组;对于单向关联,比如我有一辆自行车,但是我是可以有多辆自行车的,而自行车却只能属于某一个人,故我和自行车的关系是单向关联;在代码层面就是People类里有自行车数组,而Bike类里只有一个owner属性;
6)依赖:依赖是一种最微弱的关系,它一般是存在于局部变量,参数,或者对静态变量静态方法的引用;即它具备临时性,只是某个scope需要用到;比如A类里有调用Integer.valueOf(...),而假设A类和Integer之间没有其它的关系,那么A和Integer就是依赖关系;又比如A类中test方法用到了StringBuilder,那么StringBuilder和A类之间就是依赖关系,A依赖StringBuilder;(对于只存在依赖关系而言,两个类之间最好不要存在互相依赖,自写类依赖String,String不依赖自写类)