如何通过组合优于继承避免Java代码重复?
解决Java中组合优于继承的代码重复问题
针对你遇到的代码重复问题,核心思路是把行为逻辑从动物类中抽离出来,做成独立的可复用组件,让动物类通过持有这些组件来实现对应接口——这就是组合模式的核心应用,完美规避继承的单继承限制和代码重复问题。
具体实现步骤:
- 保留行为接口:你已经定义的
Flyer、Swimmer接口继续保留,它们负责定义行为规范,不包含具体实现。
interface Flyer { void fly(); } interface Swimmer { void swim(); }
- 抽离行为实现为独立类:把原本写在动物类里的行为逻辑(比如麻雀的飞行)单独封装成一个类,让所有需要该行为的动物都能复用:
// 通用的带翅膀飞行实现,包含数据库、日志等复杂逻辑 class WingedFlyer implements Flyer { @Override public void fly() { // 这里写复用的飞行逻辑:数据库操作、日志打印等 System.out.println("使用翅膀飞行,执行数据库集成与日志处理..."); } } // 鲑鱼的游泳实现 class FishSwimmer implements Swimmer { @Override public void swim() { System.out.println("用鱼鳍划水前进"); } }
- 动物类通过组合复用行为:动物类不再通过继承获取行为实现,而是持有行为组件的实例,在实现接口方法时,直接委托给组件处理:
abstract class Animal { protected void eat() { // 通用进食逻辑 } protected void sleep() { // 通用睡眠逻辑 } } // 麻雀类:持有飞行行为组件 class Sparrow extends Animal implements Flyer { private final Flyer flyingBehavior; public Sparrow() { // 注入通用飞行行为 this.flyingBehavior = new WingedFlyer(); } @Override public void fly() { // 委托给行为组件执行 flyingBehavior.fly(); } } // 喜鹊类:直接复用相同的飞行行为,无需重复写逻辑 class Magpie extends Animal implements Flyer { private final Flyer flyingBehavior; public Magpie() { this.flyingBehavior = new WingedFlyer(); } @Override public void fly() { flyingBehavior.fly(); } } // 鲑鱼类:持有游泳行为组件 class Salmon extends Animal implements Swimmer { private final Swimmer swimmingBehavior; public Salmon() { this.swimmingBehavior = new FishSwimmer(); } @Override public void swim() { swimmingBehavior.swim(); } }
扩展场景:多行为组合
如果需要创建同时具备多种行为的动物(比如鸭子会飞又会游),组合模式的优势就体现出来了——直接持有多个行为组件即可,完全不受单继承限制:
// 鸭子的游泳实现(和鲑鱼不同) class DuckSwimmer implements Swimmer { @Override public void swim() { System.out.println("用鸭掌拨水游泳"); } } class Duck extends Animal implements Flyer, Swimmer { private final Flyer flyingBehavior; private final Swimmer swimmingBehavior; public Duck() { this.flyingBehavior = new WingedFlyer(); this.swimmingBehavior = new DuckSwimmer(); } @Override public void fly() { flyingBehavior.fly(); } @Override public void swim() { swimmingBehavior.swim(); } }
这种方案的核心优势:
- 彻底消除代码重复:同一种行为逻辑只需要实现一次,所有需要的动物类都能复用
- 突破单继承限制:动物可以同时组合任意多种行为,无需担心继承链冲突
- 更高的灵活性:如果需要修改某类行为,只需要修改对应的行为实现类,无需改动所有使用该行为的动物类;甚至可以在运行时动态切换动物的行为(比如给受伤的鸟替换成
DisabledFlyer) - 符合开闭原则:新增行为或动物时,不需要修改现有代码,只需要新增对应的行为实现类或动物类即可
内容的提问来源于stack exchange,提问作者Link
相关产品推荐
相关产品推荐

