组合和聚合都是讨论一个类由其他类构成的情况,是一种整体和部分的关系。组合是一种很强的关系,部分对象的创建、存在、和消亡都是和整体一起的。聚合相较于组合,关系要弱一些,但也是整体和部分的关系,并非同生共死,部分实例可以添加到聚合整体,也可以从聚合整体中移出。
依赖是类作为方法的参数(或者局部变量)存在
例如:Human和Head是组合关系,构造或者回收Human,是一起的。Human和Car是聚合关系,可以对其进行替换。Human和Ball是依赖关系,Ball作为方法的参数。
public class Human {
private Head head;
private Car car;
public Human(Head head) {
this.head = head;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public String play(Ball ball) {
return "play " + ball.ball;
}
}
这3种类的关系很基础,但是要理解明白不容易。运用好这几种关系,在使用面向对象处理问题,将现实问题转换为代码描述时,很重要。
假如一个类是单例且线程安全的,如果组合或者聚合了可变的的属性,则就改变了不变的属性,可能变成非线程安全。在Spring中,Bean默认是单例的,所以再给Bean增加属性的时候,就要考虑到会不会影响其单例且线程安全。
举个例子,使用Handler处理一个长流程,会关联到一个Context,Context是可变的。如果Context作为组合或者聚合跟Handler进行关联,那么多个线程都可以改变Context。此时就不是线程安全的,该Handler也不应该成为单例,交给Spring管理这个Bean是不合适的。
public class Handler {
private Context context;
public Handler(Context context) {
this.context = context;
}
public void process() {
Properties properties = context.getProperties();
//.......
}
}
如果换为依赖关系,交给Spring管理这个Bean,成为单例就很合适。目的就是交给Spring管理,可以对其进行各种代理,不需要自己去new,好处特别多。而且也是线程安全的。
public class Handler {
public Handler() {
}
public void process(Context context) {
Properties properties = context.getProperties();
//.......
}
}
总而言之,了解类的关联关系,在设计接口,抽象定义,实现具体类过程中是很重要的。