
本文介绍在 java 中应对“类间部分行为重叠但非严格父子关系”场景的最佳实践:摒弃冗余继承,采用接口抽象 + 组合委托的组合模式,兼顾代码复用性、可扩展性与多态一致性。
本文介绍在 java 中应对“类间部分行为重叠但非严格父子关系”场景的最佳实践:摒弃冗余继承,采用接口抽象 + 组合委托的组合模式,兼顾代码复用性、可扩展性与多态一致性。
在面向对象设计中,当多个类共享部分而非全部行为(如 BikeStation 与 CanoeStation 各有专属逻辑,而 BikeAndCanoeStation 需同时具备二者能力),强行使用单继承会导致代码重复、违反 DRY 原则,且难以支持未来新增组合类型(如 BikeAndEbikeStation)。此时,组合优于继承(Composition over Inheritance) 是更符合开闭原则与单一职责原则的解决方案。
✅ 核心思路:接口定义契约,组合实现复用
我们应将共性行为抽象为接口,将特有行为封装为可插拔的组件,再通过组合方式在具体类中按需装配。这既保留多态能力(所有站点均可统一调用 doSomething()),又避免逻辑复制。
PHPCMS V9采用OOP(面向对象)方式进行基础运行框架搭建。模块化开发方式做为功能开发形式。框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求。 PHPCMS V9企业黄页主要特色1、模型自定义,支持模型添加、修改、删除、导出、导入功能;2、模型字段自定义,支持模型字段添加、修改、删除、禁用操作;3、分类无限添加,支持批量多级添加;4、新增附件字段功能,实现相同模型,不
第一步:定义清晰的行为契约接口
public interface BikeCapable {
void rentBike();
void returnBike();
int getAvailableBikes();
}
public interface CanoeCapable {
void rentCanoe();
void returnCanoe();
int getAvailableCanoes();
}✅ 优势:接口明确职责边界;支持任意类实现任一或多个接口,天然支持多态与混合能力。
第二步:实现可复用的行为组件(非 public 类或独立服务类)
为避免暴露实现细节,建议将具体逻辑封装为包级私有组件类,而非直接复用 BikeStation/CanoeStation:
// 封装自行车相关逻辑(不暴露为 public 类)
class BikeService {
private int availableBikes = 10;
public void rentBike() { /* ... */ }
public void returnBike() { /* ... */ }
public int getAvailableBikes() { return availableBikes; }
}
class CanoeService {
private int availableCanoes = 5;
public void rentCanoe() { /* ... */ }
public void returnCanoe() { /* ... */ }
public int getAvailableCanoes() { return availableCanoes; }
}第三步:构建具体站点类 —— 组合 + 接口实现
public abstract class Station {
protected String name;
protected String location;
public Station(String name, String location) {
this.name = name;
this.location = location;
}
// 所有站点共有的抽象行为(支持多态)
public abstract void open();
public abstract void close();
}
// 纯自行车站点:仅实现 BikeCapable
public class BikeStation extends Station implements BikeCapable {
private final BikeService bikeService = new BikeService();
public BikeStation(String name, String location) {
super(name, location);
}
@Override
public void open() { System.out.println(name + " (Bike only) opened."); }
@Override
public void close() { System.out.println(name + " closed."); }
// 委托至 BikeService
@Override
public void rentBike() { bikeService.rentBike(); }
@Override
public void returnBike() { bikeService.returnBike(); }
@Override
public int getAvailableBikes() { return bikeService.getAvailableBikes(); }
}
// 纯独木舟站点:仅实现 CanoeCapable
public class CanoeStation extends Station implements CanoeCapable {
private final CanoeService canoeService = new CanoeService();
public CanoeStation(String name, String location) {
super(name, location);
}
@Override
public void open() { System.out.println(name + " (Canoe only) opened."); }
@Override
public void close() { System.out.println(name + " closed."); }
@Override
public void rentCanoe() { canoeService.rentCanoe(); }
@Override
public void returnCanoe() { canoeService.returnCanoe(); }
@Override
public int getAvailableCanoes() { return canoeService.getAvailableCanoes(); }
}
// 混合站点:同时组合两个服务,并实现两个接口
public class BikeAndCanoeStation extends Station implements BikeCapable, CanoeCapable {
private final BikeService bikeService = new BikeService();
private final CanoeService canoeService = new CanoeService();
public BikeAndCanoeStation(String name, String location) {
super(name, location);
}
@Override
public void open() { System.out.println(name + " (Bike & Canoe) opened."); }
@Override
public void close() { System.out.println(name + " closed."); }
// 委托实现 —— 零重复代码
@Override
public void rentBike() { bikeService.rentBike(); }
@Override
public void returnBike() { bikeService.returnBike(); }
@Override
public int getAvailableBikes() { return bikeService.getAvailableBikes(); }
@Override
public void rentCanoe() { canoeService.rentCanoe(); }
@Override
public void returnCanoe() { canoeService.returnCanoe(); }
@Override
public int getAvailableCanoes() { return canoeService.getAvailableCanoes(); }
}第四步:验证多态与扩展性
public class StationDemo {
public static void main(String[] args) {
List<Station> stations = Arrays.asList(
new BikeStation("Central Bike Hub", "Downtown"),
new CanoeStation("River Landing", "Riverside"),
new BikeAndCanoeStation("Harbor Junction", "Waterfront")
);
// 统一多态调用基础行为
stations.forEach(Station::open);
// 类型安全地调用特有行为(利用接口)
stations.forEach(station -> {
if (station instanceof BikeCapable) {
((BikeCapable) station).rentBike();
}
if (station instanceof CanoeCapable) {
((CanoeCapable) station).rentCanoe();
}
});
// 新增组合类?只需新建类并组合对应 Service,无需修改现有逻辑
// → 完全符合开闭原则
}
}⚠️ 注意事项与最佳实践
- 避免过度继承链:不要让 BikeAndCanoeStation 继承 BikeStation 或 CanoeStation——这会引入不必要的强耦合与状态污染。
- 接口粒度要合理:按业务能力(BikeCapable)而非技术实现(Rentable)划分接口,提升语义清晰度与复用性。
- 组合对象生命周期管理:若 BikeService 需外部依赖(如数据库连接),建议通过构造器注入,便于单元测试。
- 考虑使用策略模式进阶:当某类行为存在多种算法变体(如不同计费策略),可将 BikeService 抽象为策略接口,进一步解耦。
- Java 8+ 可补充默认方法:在接口中提供通用辅助逻辑(如 default String getStationType()),减少子类重复。
✅ 总结
面对“交叉复用”场景,组合模式配合接口驱动的设计,比深度继承更灵活、更可维护。它使系统具备三大优势:
? 低耦合:各能力模块独立演进;
? 高内聚:每个组件专注单一职责;
? 强扩展性:新增站点类型只需组合已有组件,无需重构基类。
真正践行了面向对象设计的本质——关注“能做什么”,而非“是什么”。








