面向对象之类的组合、聚合、依赖

289 阅读2分钟

组合和聚合都是讨论一个类由其他类构成的情况,是一种整体和部分的关系。组合是一种很强的关系,部分对象的创建、存在、和消亡都是和整体一起的。聚合相较于组合,关系要弱一些,但也是整体和部分的关系,并非同生共死,部分实例可以添加到聚合整体,也可以从聚合整体中移出。

依赖是类作为方法的参数(或者局部变量)存在

例如: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();
        //.......
    }
}

总而言之,了解类的关联关系,在设计接口,抽象定义,实现具体类过程中是很重要的。