组合是通过在一个类中包含另一个类的实例来实现代码复用的技术,体现了“has-a”关系。例如,Car类包含Engine对象,通过调用engine.start()复用其行为。相比继承,组合降低了类间的耦合度,提高了灵活性和可维护性,支持运行时动态替换组件,避免了Java单继承的限制,并便于单元测试。实际应用中,如策略模式可通过接口注入不同实现,使Vehicle类能灵活支持汽油或电动引擎,提升系统可扩展性。推荐在多数复用场景中优先使用组合而非继承。

在Java中,组合是一种通过将已有类的实例作为新类的成员变量来实现代码复用的技术。相比继承,组合更加灵活、安全,并能有效避免继承带来的紧耦合问题。合理使用组合,可以让代码更易于维护和扩展。
什么是组合
组合指的是在一个类中包含另一个类的对象作为其字段(成员变量),从而复用该对象的行为。这种方式体现了“has-a”关系,而不是继承的“is-a”关系。
例如,一个Car类可以包含一个Engine对象,表示“汽车有一个引擎”,而不是让Car继承自Engine。
如何使用组合实现复用
通过组合复用代码的核心是:在目标类中创建被复用类的实例,并调用其方法。
立即学习“Java免费学习笔记(深入)”;
示例:
class Engine { public void start() { System.out.println("引擎启动"); } } class Car { private Engine engine; // 组合:Car 拥有 Engine public Car() { this.engine = new Engine(); } public void start() { System.out.println("汽车开始启动..."); engine.start(); // 复用 Engine 的行为 } }
在这个例子中,Car类不需要重新实现启动逻辑,而是直接使用Engine类的功能,实现了代码复用。
组合的优势
- 降低耦合度:类之间依赖的是具体对象而非继承结构,修改父类不会意外影响子类。
- 提高灵活性:可以在运行时动态替换组件,比如注入不同的Engine实现。
- 避免继承的局限性:Java不支持多继承,但一个类可以拥有多个其他类的实例。
- 便于单元测试:可以通过模拟(mock)组件对象来独立测试主类。
实际应用场景
组合广泛应用于设计模式中,如策略模式、装饰器模式等。
举例:定义不同类型的引擎行为:
interface Engine { void start(); } class GasolineEngine implements Engine { public void start() { System.out.println("汽油引擎启动"); } } class ElectricEngine implements Engine { public void start() { System.out.println("电动引擎启动"); } } class Vehicle { private Engine engine; public Vehicle(Engine engine) { this.engine = engine; } public void start() { engine.start(); } }
这样,通过传入不同的Engine实现,Vehicle可以在不修改代码的情况下支持多种引擎类型,体现了良好的可扩展性。
基本上就这些。组合让代码更模块化,推荐在大多数需要复用场景下优先于继承使用。


