类与类之间的 6 种关系

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/willway_wang/article/details/90138892

1. 前言

2016 年 8 月我去面试 Android 的时候,遇到一个 Java 大牛,问过我这个问题。我确实不知道类与类之间竟然会有 6 种关系。面试后,虽然查了一下,但是依然不理解:类与类之间这 6 种关系是怎么总结出来的。

2. 正文

2.1 继承(generalization)

这个大家都不陌生,可以说是非常熟悉了。使用继承,我们能够以现有类为基础(获取它的全部可继承的成员),通过添加或修改一些成员来创建新类。源类常被称为基类、超类或者父类,导出类常被称为继承类或者子类。以经典的几何形的例子来说明:

Shape 类是父类,而 Circle、Square、Triangle 是三个子类,通过继承子类获得了父类的全部可继承的成员。
但是,子类难道仅仅是为了获取父类的全部可继承的成员而已吗?
显然不是,如果仅仅那样,何不直接使用父类呢?
子类通常会和父类产生差异,有两种办法可以实现。
第一种产生差异的办法是直接在子类中添加新的方法(这些新方法并不是父类的方法),这样就扩展了接口,这种情况下子类和父类是 is-like-a(像是一个)关系。
第二种产生差异的办法是改变现有父类的方法的行为(这被称为覆盖 override),这种情况下子类和父类是 is-a(是一个)关系。替代原则适用于这种情况。

2.2 实现(realization)

这是类与接口之间的关系。注意类实现接口,需要用到的是 implements 关键字。下边使用 Java 编程思想中的例子说明:

代码如下:

interface Instrument {
    void play();
    String what();
    void adjust();
}

class Wind implements Instrument {

    @Override
    public void play() {
        System.out.println("Wind " + "play()");
    }

    @Override
    public String what() {
        return "Wind what()";
    }

    @Override
    public void adjust() {
        System.out.println("Wind " + "adjust()");

    }
}

class Percussion implements Instrument {

    @Override
    public void play() {
        System.out.println("Percussion " + "play()");
    }

    @Override
    public String what() {
        return "Percussion what()";
    }

    @Override
    public void adjust() {
        System.out.println("Percussion " + "adjust()");
    }
}

class Stringed implements Instrument {

    @Override
    public void play() {
        System.out.println("Stringed " + "play()");
    }

    @Override
    public String what() {
        return "Stringed what()";
    }

    @Override
    public void adjust() {
        System.out.println("Stringed " + "adjust()");
    }
}

2.3 依赖(dependency)

依赖关系是一种使用关系。如果一个类A通过new关键字创建了另一个类B的实例, 那么独立于类B去使用或者测试类A是不行的. 这时, 类A和类B就存在dependency. 类A被叫做dependant, 类B被叫做 dependency. A dependant depends on its dependencies, 在这里, 类A依赖于类B。依赖可以理解为耦合。
依赖确实是有缺点的:代码复用性差,难以测试,难以维护。
依赖的分类:类依赖,接口依赖,方法/属性依赖,直接或间接的依赖。

2.4 关联(association)

表示两个不相关的对象之间的关系。两个单独的类通过它们的对象发生关联。两个类是不相关的,也就是说一个类可以单独存在在另外一个类不存在的情况下。可以是一对一、一对多、多对一、一对一的关系。

2.5 聚合(aggregation)

聚合是关联的一种。如果组合是动态发生的,通常被称为聚合(aggregation)。聚合是一种弱的“拥有”关系,它体现的是 A 对象包含 B 对象,但 B 对象并不是 A 对象的一部分。比如车队里包含有多个车,人群里包含有多个人。它只是一种单方向的关系,比如车队包含车,但车并不包含车队。

2.6 组合(composition)

使用现有的类合成新的类,这就是组合(composition)。组合经常被视为“has-a”(拥有)关系,组合是一种强的“拥有”关系,体现的是严格的部分和整体的关系,部分和整体的生命周期是一样的(整体离不开部分,部分也离不开整体)。比如汽车拥有引擎,人拥有腿。在 UML 图中,使用实心菱形来表示组合关系。
组合非常直观,只需要在新类中产生现有类的对象,这样新的类就由现有类的对象所组成。组合只是复用了现有代码的功能,而不是现有代码的形式。

使用代码表示如下:

public class Car {
    private Engine mEngine;
}

class Engine {
    
}
public class Person {
    private Leg mLeg;
}

class Leg {

}

3. 最后

简单地介绍了一下类与类之间的 6 种关系,希望能够帮助到大家。

猜你喜欢

转载自blog.csdn.net/willway_wang/article/details/90138892