谈一谈自己对依赖、关联、聚合和组合之间区别的理解

在学习面向对象设计对象关系时,依赖、关联、聚合和组合这四种关系之间区别比较容易混淆。特别是后三种,仅仅是在语义上有所区别,所谓语义就是指上下文环境、特定情景等。他们在编程语言中的体现却是基本相同的,但是基本相同并不等于完全相同,这一点在我的前一篇博文《设计模式中类的关系》中已经有所提及,下面就来详细的论述一下在Java中如何准确的体现依赖、关联、聚合和组合。

首先看一看书上对这四种关系的定义:

  • 依赖(Dependency)关系是类与类之间的联接。依赖关系表示一个类依赖于另一个类的定义。例如,一个人(Person)可以买车(car)和房子(House),Person类依赖于Car类和House类的定义,因为Person类引用了Car和House。与关联不同的是,Person类里并没有Car和House类型的属性,Car和House的实例是以参量的方式传入到buy()方法中去的。一般而言,依赖关系在Java语言中体现为局域变量、方法的形参,或者对静态方法的调用。
  • 关联(Association)关系是类与类之间的联接,它使一个类知道另一个类的属性和方法。关联可以是双向的,也可以是单向的。在Java语言中,关联关系一般使用成员变量来实现。
  •  聚合(Aggregation) 关系是关联关系的一种,是强的关联关系。聚合是整体和个体之间的关系。例如,汽车类与引擎类、轮胎类,以及其它的零件类之间的关系便整体和个体的关系。与关联关系一样,聚合关系也是通过实例变量实现的。但是关联关系所涉及的两个类是处在同一层次上的,而在聚合关系中,两个类是处在不平等层次上的,一个代表整体,另一个代表部分。
  •  组合(Composition) 关系是关联关系的一种,是比聚合关系强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分对象的生命周期,组合关系是不能共享的。代表整体的对象需要负责保持部分对象和存活,在一些情况下将负责代表部分的对象湮灭掉。代表整体的对象可以将代表部分的对象传递给另一个对象,由后者负责此对象的生命周期。换言之,代表部分的对象在每一个时刻只能与一个对象发生组合关系,由后者排他地负责生命周期。部分和整体的生命周期一样。

——摘自《Java面向对象编程》,作者:孙卫琴

       以上关系的耦合度依次增强(关于耦合度的概念将在以后具体讨论,这里可以暂时理解为当一个类发生变更时,对其他类造成的影响程度,影响越小则耦合度越弱,影响越大耦合度越强)。由定义我们已经知道,依赖关系实际上是一种比较弱的关联,聚合是一种比较强的关联,而组合则是一种更强的关联,所以笼统的来区分的话,实际上这四种关系、都是关联关系。

        依赖关系比较好区分,它是耦合度最弱的一种,在java中表现为局域变量、方法的形参,或者对静态方法的调用,如下面的例子:Driver类依赖于Car类,Driver的三个方法分别演示了依赖关系的三种不同形式。

[java] view plaincopy
  1. class Car {  
  2.     public static void run(){  
  3.         System.out.println("汽车在奔跑");  
  4.     }  
  5. }  
  6.   
  7. class Driver {  
  8.     //使用形参方式发生依赖关系  
  9.     public void drive1(Car car){  
  10.         car.run();  
  11.     }  
  12.     //使用局部变量发生依赖关系  
  13.     public void drive2(){  
  14.         Car car = new Car();  
  15.         car.run();  
  16.     }  
  17.     //使用静态变量发生依赖关系  
  18.     public void drive3(){  
  19.         Car.run();  
  20.     }  
  21. }  

        关联关系在java中一般使用成员变量来实现,有时也用方法形参的形式实现。依然使用Driver和Car的例子,使用方法参数形式可以表示依赖关系,也可以表示关联关系,毕竟我们无法在程序中太准确的表达语义。在本例中,使用成员变量表达这个意思:车是我自己的车,我“拥有”这个车。使用方法参数表达:车不是我的,我只是个司机,别人给我什么车我就开什么车,我使用这个车。

[java] view plaincopy
  1. class Driver {  
  2.     //使用成员变量形式实现关联  
  3.     Car mycar;  
  4.     public void drive(){  
  5.         mycar.run();  
  6.     }  
  7.     ...  
  8.     //使用方法参数形式实现关联  
  9.     public void drive(Car car){  
  10.         car.run();  
  11.     }  
  12. }  

        聚合关系是是一种比较强的关联关系,java中一般使用成员变量形式实现。对象之间存在着整体与部分的关系。例如上例中

[java] view plaincopy
  1. class Driver {  
  2.     //使用成员变量形式实现聚合关系  
  3.     Car mycar;  
  4.     public void drive(){  
  5.         mycar.run();  
  6.     }  
  7. }  


        假如给上面代码赋予如下语义:车是一辆私家车,是司机财产的一部分。则相同的代码即表示聚合关系了。聚合关系一般使用setter方法给成员变量赋值。

假如赋予如下语义:车是司机的必须有的财产,要想成为一个司机必须要先有辆车,车要是没了,司机也不想活了。而且司机要是不干司机了,这个车就砸了,别人谁也别想用。那就表示组合关系了。一般来说,为了表示组合关系,常常会使用构造方法来达到初始化的目的,例如上例中,加上一个以Car为参数的构造方法

[java] view plaincopy
  1. public Driver(Car car){  
  2.     mycar = car;  
  3. }  


        所以,关联、聚合、组合只能配合语义,结合上下文才能够判断出来,而只给出一段代码让我们判断是关联,聚合,还是组合关系,则是无法判断的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351379.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java Bullshifier –生成大量随机代码库

生成大量随机Java应用程序的命令行工具 您一直在等待的命令行工具。 或不。 毕竟,这是很深奥的。 无论哪种方式,它对某些人都非常有用,而对其他人来说却是一个有趣的实用程序。 Bullshifier是由David Levanon和Hodaya Gamliel开发的内部Over…

二级c语言光盘,二级c语言(光盘).doc

1程序设计题: 请编写一个函数 unsigned fun (unsigned w ) w是一个大于10的无符号整数。例如:W值为5923,则函数返回923;W值为923,则函数返回23。if ( w >10000 ) w % 10000 ; 程序修改题: m i; 和 if( a[k]>a[m]…

设计模式六大原则(3):依赖倒置原则

定义: 高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下…

Jirasearch 2.0狗粮:使用Lucene查找我们的Jira问题

几年前,我首先构建并发布了Jirasearch ,它是用于薄型包装Lucene服务器的有趣的狗粮测试用例,以针对我们的Jira问题公开强大的搜索UI。 这很好地展示了Lucene的许多重要功能: 使用块联接查询来建模父文档(原始的Jira问…

Highcharts教程--把js代码从html中抽离出来,放到单独的一个js文件中。由html页面调用...

1.html页面写法 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>第一个 Highcharts 图表</title><!-- 引入 jquery.js --><script src"static/jquery-3.3.1.min.js"><…

数据结构c语言版第16页,数据结构c语言版

数据结构c语言版[编辑]概述《数据结构C语言版》本书的前半部分从抽象数据类型的角度讨论各种基本类型的数据结构及其应用;后半部分主要讨论查找和排序的各种实现方法及综合分析比较出版信息作/译者&#xff1a;严蔚敏&#xff0c;吴伟民 出版社&#xff1a;清华大学出版社出版日…

C语言申请内存时堆栈大小限制

一直都有一个疑问&#xff0c;一个进程可以使用多大的内存空间&#xff0c;swap交换空间以及物理内存的大小&#xff0c;ulimit的stack size对进程的内存使用有怎样的限制&#xff1f;今天特亲自动手实验了一次&#xff0c;总结如下&#xff1a; 开辟一片内存空间有2种方式&…

微服务之数据同步Porter

Porter是一款数据同步中间件&#xff0c;主要用于解决同构/异构数据库之间的表级别数据同步问题。 背景 在微服务架构模式下深刻的影响了应用和数据库之间的关系&#xff0c;不像传统多个服务共享一个数据库&#xff0c;微服务架构下每个服务都要有自己的数据库。如果你想获得微…

C语言采用多文件的工程结构百度,C语言学习知识复习资料结构框架学习知识重点.doc...

C语言学习知识复习资料结构框架学习知识重点.doc .思维导图1C语言程序设计知识结构第一课 C语言程序设计基础思维导图2第一课 C语言程序设计基础本课主要知识点1.知识点C程序基础l C语言是一种结构化程序设计语言。三种基本结构顺序、选择、循环。例1(2010-09-11)以下关于结构化…

antlr_ANTLR –语义谓词

antlr用antlr解析简单的语法很简单 。 您要做的就是使用正则表达式描述您的语言&#xff0c;并让antlr生成词法分析器和解析器。 解析大型或复杂的语言有时会需要更多&#xff0c;因为仅使用正则表达式描述它们是困难的&#xff0c;甚至是不可能的。 语义谓词是在语法内部编写…

栈大小和内存分部问题

今天面试问了一个栈大小问题&#xff0c;问过两次内存的结构问题&#xff0c;都没有答好&#xff0c;这次要弄清楚才行。 栈大小是有默认值的&#xff0c;如果申请的临时变量太大的话就会超过栈大小&#xff0c;造成栈溢出。 编译期限制栈大小&#xff0c;和系统限制栈深度根本…

ssh登陆报错“WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!”的解决方法

解决方法&#xff1a;删除 ~/.ssh/known_hosts转载于:https://www.cnblogs.com/liangxc/p/10414123.html

android 动态修改菜单,如何在Android的“选项”菜单上更改MenuItem?

如何在Android的“选项”菜单上更改MenuItem&#xff1f;我的Activity上有一个选项菜单&#xff0c;带有mymenu.xml“开始”。 选择此3000128611611048489985后&#xff0c;我想更改菜单&#xff0c;使其包含MenuItem“停止”。 最后&#xff0c;当选择“停止”时&#xff0c;我…

Java性能监控:您应该了解的5个开源工具

鲜为人知但有用&#xff1a;开源应用程序性能监视的状态 对于任何应用程序来说&#xff0c;最重要的事情之一就是性能。 我们要确保用户获得他们能获得的最佳体验&#xff0c;并且要知道我们的应用已启动并正在运行。 这就是为什么我们大多数人至少使用一种监视工具的原因。 …

【BZOJ1069】【SCOI2007】—最大土地面积(凸包+旋转卡壳)

传送门 考虑枚举任意222个点&#xff0c;那么只需要枚举第二个点的时候旋转卡壳就可以O(n)O(n)O(n)得到最远点对了 #include<bits/stdc.h> using namespace std; inline int read(){char chgetchar();int res0,f1;while(!isdigit(ch)){if(ch-)f-f;chgetchar();}while(isd…

如何在vs2010中修改栈的大小

上次运行程序的时候提示栈溢出&#xff0c;oh,my god 程序栈空间不够用了&#xff0c;没关系&#xff0c;可以设置栈的大小&#xff0c;默认是1MB。 选择 项目->属性->链接器->系统->堆栈保留大小,然后输入你想要的栈大小即可。

android第三方登录appid,AndroidQQ第三方登录

集成QQ登录在lib导入该open_sdk_r5886_lite.jar包AndroidManifest.xmlandroid:name"com.tencent.tauth.AuthActivity"android:launchMode"singleTask"android:noHistory"true" >android:theme"android:style/Theme.Translucent.NoTitleB…

Java数组、集合的三种遍历方式(包懂)

1 for循环 for(int i 0;i<arr.length;i){System.out.print(arr[i]" "); } 2 foreach循环&#xff0c;这种方式结构简单&#xff0c;可以简化代码 for(int i:arr){System.out.print(arr[i]" "); } 3 迭代器遍历 对于数组而言&#xff0c;就没必要转换为…

你应当如何学习C++(以及编程)(rev#1)

你应当如何学习C(以及编程)(rev#1) By 刘未鹏(pongba) C的罗浮宫(http://blog.csdn.net/pongba) JavaScript是世界上最受误解的语言&#xff0c;其实C何尝不是。坊间流传的错误的C学习方法一抓就是一大把。我自己在学习C的过程中也走了许多弯路&#xff0c;浪费了不少时间。 为…

android 悬浮窗口和主界面同时显示,Android 悬浮窗口(及解决6.0以上无法显示问题)...

思路实现通过WindowManager添加一个View&#xff0c;创建一个系统顶级的窗口&#xff0c;实现悬浮窗口的效果。本篇思路&#xff0c;来源于郭霖大神的悬浮窗口教程。大致介绍WindowManager 类创建的对象&#xff1a;Context.getSystemService(Context.WINDOW_SERVICE)常用API:a…