Java 中 组合 (Composition)、接口 (Interface) 和 委托 (Delegation) 这三个概念的区别

Java中组合、接口与委托的区别

备注:

1、本文内容大部分内容是通过AI查询而来的。然后我进行了总结和修改。

2、本文是在学习极客时间王争老师的《设计模式之美》-《10 | 理论七:为何说要多用组合少用继承?如何决定该用组合还是继承?》时,所做的一些记录和思考。

本文将讲解一下 Java组合 (Composition)接口 (Interface)委托 (Delegation) 这三个概念的区别,并通过 Java 代码示例进行说明。

特性组合 (Composition)接口 (Interface)委托 (Delegation)
定义类 A 包含类 B 的一个实例作为其成员变量。定义一组方法签名,但不提供实现。类 A 将某些职责交给类 B 的实例来完成。
关系“拥有” (has-a) 关系。“契约”“能力” 关系。“转交” (forwarding) 职责。
目的重用现有类的功能,实现功能聚合。实现多态,定义公共行为规范,解耦实现。在不使用继承的情况下实现代码重用功能扩展
实现通过在类中创建另一个类的对象实例。通过 interface 关键字和 implements 关键字。通过组合,并在包含类中显式地调用成员对象的方法。
优点高度灵活,可以随时替换内部对象。强制实现约定方法,支持多重实现。替代继承,提供更灵活的运行时行为。
1. 接口 (Interface)

接口定义了对象可以做什么(能力/行为),而不关心如何实现。

/**
 * 接口:定义“可打印”的能力
 */
public interface Printable {
    // 定义一个打印方法,所有实现该接口的类都必须实现此方法
    void print(String content);
}

/**
 * 实现类 A:激光打印机
 */
public class LaserPrinter implements Printable {
    @Override
    public void print(String content) {
        System.out.println("激光打印机正在高速打印: " + content);
    }
}

/**
 * 实现类 B:喷墨打印机
 */
public class InkjetPrinter implements Printable {
    @Override
    public void print(String content) {
        System.out.println("喷墨打印机正在彩色打印: " + content);
    }
}

关键点: Printable 定义了契约,LaserPrinterInkjetPrinter 提供了不同的实现,实现了多态。

2. 组合 (Composition)

组合是类 A 拥有类 B 的实例,从而重用类 B 的功能。

/**
 * 使用组合的 Document 类
 * Document “拥有”一个 LaserPrinter 实例
 */
public class Document {
    // 1. 组合:Document 内部有一个 LaserPrinter 的实例 (has-a 关系)
    private LaserPrinter myPrinter; 
    
    public Document() {
        // 实例化内部对象
        this.myPrinter = new LaserPrinter();
    }
    
    public void printMyDocument(String text) {
        System.out.println("--- Document 准备打印 ---");
        // 2. Document 使用其内部 Printer 的功能
        myPrinter.print(text); 
        System.out.println("--- 打印完成 ---");
    }
}

关键点: Document 不需要知道如何打印,它将打印工作委托给内部的 LaserPrinter 对象完成。

3. 委托 (Delegation)

委托是一种设计模式,它结合了组合和接口。一个对象(委托者)将自己的某个操作的实现交给另一个对象(被委托者)来完成。这是组合的更灵活的用途,通常用于替代继承

/**
 * 使用委托的 SmartPrinter 类
 * SmartPrinter 将打印的职责委托给一个实现了 Printable 接口的对象
 */
public class SmartPrinter implements Printable {
    
    // 1. 组合:SmartPrinter 拥有一个 Printable 类型的成员变量
    private Printable delegatePrinter; 

    // 构造函数:运行时可以决定使用哪种打印机 (高度灵活)
    public SmartPrinter(Printable printer) {
        this.delegatePrinter = printer;
    }
    
    // 2. 委托:SmartPrinter 实现 Printable 接口,并将实现转交给内部对象
    @Override
    public void print(String content) {
        System.out.println("SmartPrinter 正在处理请求...");
        // 显式委托调用:将实际工作转发给 delegatePrinter
        delegatePrinter.print(content); 
        System.out.println("SmartPrinter 完成转发。");
    }
}

// --- 运行示例 ---
public class Main {
    public static void main(String[] args) {
        // 1. 创建被委托者(一个 InkjetPrinter)
        Printable inkjet = new InkjetPrinter(); 
        
        // 2. 创建委托者,将被委托者传入
        SmartPrinter smartPrinter = new SmartPrinter(inkjet);
        
        // 3. 调用委托者的方法,实际工作由被委托者完成
        smartPrinter.print("项目报告 V3.0"); 
        
        // 4. 运行时可以改变内部对象(这是委托比继承更灵活的地方)
        SmartPrinter newSmartPrinter = new SmartPrinter(new LaserPrinter());
        newSmartPrinter.print("紧急通知");
    }
}

关键点: SmartPrinterprint 方法简单地调用了内部 delegatePrinterprint 方法,这就是 委托。它实现了 Printable 接口(契约),并通过 组合(拥有内部对象)来完成功能。

总而言之:

  • 接口是定义能力 (What)契约

  • 组合是定义拥有关系 (Has-a)结构

  • 委托是一种设计模式,利用组合来实现接口定义的行为,转交职责

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值