继承和组合

文章讨论了在面向对象编程中,复杂的继承关系可能导致类的数量急剧膨胀,降低代码可读性和复用性。为了解决这一问题,提出了使用接口和组合的设计策略。通过实现接口,如FlyI和MigrateI,可以避免指数级增长的类数量。然而,接口实现可能导致代码重复。组合模式的引入,将行为封装在独立的类中,如Fly和Migrate,然后在需要的类中通过实例化这些行为类来调用相应功能,提高了代码的复用性和可读性,遵循了“多组合,少继承”的设计原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

之前我们讲了对象的继承,并且有一个设计原则就是尽量避免复杂的继承关系,否则会降低代码可读性。并且会导致类的数量膨胀,最后无法收拾。
对于这种情况,我们简单举一个例子:
问题,有一个Bird类,他的子类有很多,比如鸵鸟(ostrich),乌鸦(crow)等等。他们分为会飞和不会飞,所以在抽象父类 Bird的基础上我们还要再实现两个抽象父类,会飞的鸟和不会飞的鸟。类图如下:
在这里插入图片描述
如果仅仅是这样,还不复杂,但是如果还有其他区分,比如会叫的鸟和不会叫的鸟,会迁徙和不会迁徙的鸟,这个时候就会有很多的组合,比如会飞,会叫,会迁徙的鸟;会飞,会叫,不会迁徙的鸟;。。。 类图如下:

可以看到这里类出现了指数级别的增长,每增加一种行为,类的数量就会增加一倍,所以复杂的继承会造成灾难性的后果。

解决

对于上面继承的问题,有人可能会说,可不可以用接口的方式实现呢。当然可以,这样我们就只需要实现两个接口,FlyI和Migrate 。然后对应的子类实现这个接口就可以解决问题。

public interface FlyI {
   void fly();
}

public interface MigrateI {
   void migrate();
}

public class Pigeon extends AbstarctBird implements FlyI, MigrateI {
   @override
   public void fly(){
      System.out.println("fly");
   }
   @override
   public void migrate(){
      System.out.println("migrate");
   }
}

但是这里还有一个问题就是代码的复用性,比如会飞的鸟类,有鸽子,老鹰,麻雀,黄鹂等等,这些子类都有实现一遍Fly接口的fly方法,就造成了代码的巨大重复,不符合Java代码的设计规范。那么怎么解决这个问题,那就是组合。

组合

组合顾名思义就是一些行为的按需求放在一起。上面问题实现如下:

// 飞能力类
public class Fly {
   public void fly(){
     System.out.println("fly");
   }
}
// 迁徙能力类
public class Migrate {
  public void migrate(){
    System.out.println("migrate")
 }
}
// 使用组合的实现
public class Pigeon extends AbstarctBird {
   Fly fly = new Fly();
   Migrate migrate = new Migrate();
   public void fly(){
      fly.fly();
   }
   public void migrate(){
      migrate.migrate();
   }
}

可以看到使用组合之后轻松解决了上面的问题,即没有出现类的指数级增长,也没有出现代码的重复,代码的可读性也很高。

原则

多组合,少继承。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值