委托模式是通过组合+接口引用+方法转发手动实现的设计模式,核心是持有接口类型成员并委托调用,需构造注入避免耦合,强调“has-a”复用而非继承“is-a”,注意空指针、过度委托及职责边界。

委托模式不是Java语言特性,而是手动实现的设计模式
Java本身没有 delegate 关键字(不像C#或Kotlin),所谓“Java委托模式”就是通过**组合 + 接口引用 + 方法转发**手动模拟。核心是:一个类不继承另一个类,而是持有一个接口类型的成员变量,并把相关操作委托给它。
典型写法:接口定义 + 委托类 + 委托持有者
常见错误是直接在持有者里 new 具体实现类,导致耦合;正确做法是构造时注入,便于替换和测试。
- 定义统一行为接口,比如
Processor - 编写具体实现类,如
FileProcessor、NetworkProcessor - 委托持有者(如
TaskExecutor)持有一个Processor类型字段,在方法中调用processor.doWork() - 构造器或 setter 支持传入不同实现,实现运行时切换
public interface Processor {
void doWork();
}
public class FileProcessor implements Processor {
public void doWork() { System.out.println("Processing file"); }
}
public class TaskExecutor {
private final Processor processor;
public TaskExecutor(Processor processor) {
this.processor = processor; // 注入,非 new
}
public void execute() {
processor.doWork(); // 委托调用
}
}
与继承的区别:避免“is-a”,专注“has-a + uses-a”
继承表达的是类型关系(SubClass extends SuperClass),而委托强调能力复用。一旦你发现子类只是“用到了父类功能”,却不需要多态向上转型,那大概率该用委托。
- 继承会暴露父类所有 public/protected 成员,破坏封装;委托只暴露接口定义的方法
- 继承层级深了难以维护;委托可自由组合多个接口实例(比如同时持
Validator和Logger) - Java单继承限制下,委托是复用多个行为的唯一干净方式
容易踩的坑:空指针、过度委托、忘记接口契约
最常出问题的是没校验委托对象是否为 null,尤其在 setter 方式注入时;另外有人把每个方法都无脑转发,反而让代码更难读。
立即学习“Java免费学习笔记(深入)”;
- 在委托方法入口加
Objects.requireNonNull(processor)或构造器强制非空 - 只委托真正需要复用的行为,不要为了“设计模式感”而委托 toString()/equals()
- 接口方法语义要清晰——比如
Processor.process()和Processor.validate()不应混在一个接口里
委托模式真正的复杂点不在写法,而在**职责边界的判断**:哪些逻辑该放进委托类,哪些该留在持有者?这得结合业务场景反复推敲,而不是套模板。










