来讨论一下Java中,依赖和关联,聚合和组合的区别和联系。
依赖和关联
依赖
依赖的简单理解就是,类A中用到了另一个类B,类B的变化会影响到类A
举个例子:我用笔写字,先创建一个类Me代表自己,然后需要一个类Pen来代表一支笔,最后,“Me”调用“Pen”的方法来写字
public class Pen {
public void write() {
System.out.println("有人正在用我写字。");
}
}
public class Me {
public void UsePenToWrite(Pen pen) {//pen作为Me类方法的参数
pen.write();
}
}
关联
关联是一种常见的二元关系,描述两个类之间的活动,比如,“我”拿“笔”写字是Me类和Pen类之间的一种关联
被关联类B以类属性的形式出现在关联类A中,或者关联类A中引用了一个类型为被关联类B的全局变量,就叫做关联
与依赖不同的是,pen作为You类中的一个属性,而不是作为方法的参数传进去
public class Pen {
public void write() {
System.out.println("有人正在用我写字。");
}
}
public class You {
private Pen pen;//pen(Pen类)作为You类的属性
public void UsePenToWrite() {
pen = new Pen();
pen.write();
}
}
聚合和组合
聚合和组合都是关联的一种特殊形式,代表了两个对象之间的归属关系
从语义上来讲
如果一个对象可以被多个其他的聚集对象所拥有,那它和聚集对象之间的关系就称为聚合
如果一个对象只能归属于一个聚集对象,那么它和聚集对象之间的关系就称为组合
从内容、地址的角度来讲
聚合 => 在类中没有开辟新的空间 => 拷贝地址 => 浅拷贝
组合 => 在类中开辟了新的空间 => 拷贝内容 => 深拷贝
举个聚合、组合的例子(个人觉得这个例子是精华)
根据语义,因为每个学科的作业本都是唯一的,设定Book类和Practice类之间的关系为组合;因为一支笔可以写多本作业,设定Pen类和Practice类之间的关系为聚合
//Pen.java
public class Pen {
private int length;
private String color;
public Pen() {
length = 10;
color = "white";
}
public Pen(int length,String color) {
this.length = length;
this.color = color;
}
public void SetPen(int length,String color) {
this.length = length;
this.color = color;
}
public String toString() {
String str;
str = "length: " + length +
"\ncolor: " + color;
return str;
}
}
//Book.java
public class Book {
private int area;
private String color;
public Book() {
area = 20;
color = "white";
}
public Book(Book book) {
area = book.area;
color = book.color;
}
public Book(int area,String color) {
this.area = area;
this.color = color;
}
public void SetBook(int area,String color) {
this.area = area;
this.color = color;
}
public String toString() {
String str;
str = "area: " + area +
"\ncolor: " + color;
return str;
}
}
//practice.java
public class practice {
private String name;
private Pen pen;
private Book book;
public practice(String name,Pen pen,Book book) {
this.name = name;
this.pen = pen;//聚合,把pen的地址拷贝给了this.pen
this.book = new Book(book);//组合,开辟一个新的内存空间
}
public void SetBook(Book newbook) {
book = new Book(newbook);
}
//聚合
public Pen getPen() {
return pen;
}
//组合
public Book getBook() {
return new Book(book);
}
public String toString() {
String string;
string = "practice Name: " + name +
"\nPen Information:\n" + pen +
"\nBook Information:\n" + book;
return string;
}
}
//practice.java
public class practiceDemo {
public static void main(String[] args) {
Pen mypen = new Pen(100,"black");
Book mybook = new Book();
practice mypractice = new practice("math",mypen,mybook);
System.out.println(mypractice);//第一组输出
System.out.println();
mypen.SetPen(10,"red");
System.out.println(mypractice);//第二组输出
System.out.println();
mybook.SetBook(30,"brown");
System.out.println(mypractice);//第三组输出
System.out.println();
mypractice.SetBook(new Book(30,"brown"));
System.out.println(mypractice);//第四组输出
}
}
第一组输出
practice Name: math
Pen Information:
length: 100
color: black
Book Information:
area: 20
color: white
原本mypratice中的值
第二组输出
practice Name: math
Pen Information:
length: 10
color: red
Book Information:
area: 20
color: white
通过SetPen()更新了mypen,mypractice中的pen属性的值同样也发生了改变,最后的输出结果是改变后的值,说明是把mypen的地址赋值给了mypractice中的pen属性,这就是Pen类和Practice类之间的组合关系
第三组输出
practice Name: math
Pen Information:
length: 10
color: red
Book Information:
area: 20
color: white
通过SetBook()更新了mybook,但最后的输出并没有改变,mypractice中的book属性的值同没有被改变,说明最初只是把mybook中的内容赋值给了mypractice中的book属性,这就是Book类和Practice类之间的聚合关系
第四组输出
practice Name: math
Pen Information:
length: 10
color: red
Book Information:
area: 30
color: brown
通过mypractice的SetBook()方法,向其中传入一个新的Book类,才能将这个类的内容赋值给mypractice中的book属性,从而使最后的输出发生改变
聚合
在代码层面,联合和关联是一致的。在普通的关联关系中,A类和B类没有必然的联系,但在聚合中,B类是A类的一部分,是一种“has-a”的关系;A是整体,B是部分,整体和部分之间是可以分离的,他们可以具有各自的生命周期,部分可以属于多个整体对象,也可以多个整体对象共享
组合
组合是一种“contains-a”的关系,这种关系比聚合更强;组合同样体现整体与部分间的关系,与聚合不同的是,整体和部分是不可分的,整体生命周期的结束就意味着部分生命周期的结束,并且部分只能属于一个对象
本文章参考:https://blog.youkuaiyun.com/qq_31655965/article/details/54645220