我应该使用 class 继承吗?

Should i use class inheritance or not?

我必须为客户管理会费。我制作了一个名为 Due 的 class。它存储两类客户 X、Y 的会费。它是这样的。

public abstract class Due  {

  private CustomerType customerType; //can be either X or Y 
  protected DueType dueType;
  private String dueId;
  private BigDecimal dueAmount;
  private Date dueDate;

  public Due(CustomerType type) {
     this.customerType = type;
  }

  //getters , setters goes here.
}

另外 DueType 对于 X 和 Y 都是不同的。因此我创建了一个名为 DueType 的接口和枚举 XDueType, YDueType 实现了它。

public interface DueType {
}

public enum XDueType implements DueType {
   A, B;
}

public enum YDueType implements DueType {
   C, D;
}

我有两个不同的 classes,每个都专门针对 X 和 Y 的到期日。像这样

public class XDue extends Due {

   public XDue() {
     super(CustomerType.X);
   }

   public XDueType getDueType() {
     return (XDueType) this.dueType;
   }

}

public class YDue extends Due {

   public YDue() {
     super(CustomerType.Y);
   }

   public YDueType getDueType() {
     return (YDueType) this.dueType;
   }
}

我必须对 Due 进行大量操作,无论其类型如何(这些操作对于 XDueYDue).

我的问题是我是否应该像上面那样在这里使用继承。我本可以只做一个 class Due。那本来可以简单地为我完成工作。但是前一种方法对我来说似乎在语义上更正确。此外,向前 XDueYDue 可能会变得不那么相似。因此,我认为最好从现在开始将它们分开。我对么?

听起来 class 需要一些重构 - 目前它是继承和组合的混合体。我建议完全单向或另一种方式

完全继承会将所有条件逻辑移动到派生类中,并且任何 "types" 返回都是无状态单例(枚举对此很有用)。理想情况下,通过进一步重构,您也可以将任何类型依赖代码移动到派生的 classes 中。

public enum DueType { X, Y }
public enum CustomerType {X,Y}

public abstract class Due  {

  private String dueId;
  private BigDecimal dueAmount;
  private Date dueDate;

  public Due(CustomerType type) {
     this.customerType = type;
  }

  abstract DueType getDueType();
  abstract CustomerType getCustomerType();
}

public class XDue extends Due {

   @Override public DueType getDueType() {
     return DueType.X;
   }

   @Override public CustomerType getCustomerType() {
     return CustomerType.X;
   }
}

或者进行完整组合,其中 Due 是最终的,并将其决定推迟到包含的策略类型。同样,任何打开类型的逻辑通常都可以移入策略 classes.

public interface DueType /* Really a strategy now */ {
   void doSomeThing(Due d);
}

public interface CustomerType  /* Really a strategy now */ {
   void doSomething(Due d);
}

public final class Due {

  private String dueId;
  private BigDecimal dueAmount;
  private Date dueDate;
  DueType dueType;
  CustomerType customerType;    

  public Due(CustomerType type, DueType dueType) {
     this.customerType = type;
     this.dueType = dueType
  }
}

public class XDueType implements DueType {
...
}

public clasx XCustomerType implements CustomerType {
...
}

组合优于继承的优势在于,它可以更清晰地实现不相关的 DueType 和 Customer 类型的其他变体,即具有 CustomerTypeADueTypeBDue 对象,而无需需要创建 DueAB class。 (但如果这在您的情况下是不可能的,那么这种潜在的差异是一件坏事)。

另一个优点是您可以在 运行 时更改策略,而无需创建全新的 Due 对象。但同样,这可能不是需要/想要的东西。

是的,您的方向是正确的。这是模板模式之王。 你可以使用泛型的一件事,因为你有相同类型的到期和客户:

public abstract class Due<T, U>  {

  private U customerType; //can be either X or Y 
  protected T dueType;
  private String dueId;
  private BigDecimal dueAmount;
  private Date dueDate;

  public Due(Utype) {
     this.customerType = type;
  }

  //getters , setters goes here.
}