有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java继承与否

我正在处理一个部件,该部件应:

  1. 从某些外部计算组件接收数据(项目集合)。我预计每个请求的输入中大约有100-1K项

  2. 验证数据,如果缺少,则计算某些属性

  3. 持久化数据

大约有十种类型的物品。我使用继承对项目进行建模。我有一个具有公共属性和计算的基本项类,以及实现特定类型问题的子类。与以下示例类似:

public abstract class BaseItem {
    String name;
    boolean valid = true;

    public void postCalucate() {
        //common calculation
                    valid = valid && (name != null);
    }
}

public   class ItemA extends BaseItem {
    BigDecimal value;

    @Override
    public void postCalucate() {
        //some A specific calculations                        
        super.postCalucate();
    }
}

public   class ItemA1 extends ItemA {
    BigDecimal extraValue;

    @Override
    public void postCalucate() {
        //some A1 subtype specific calculations
               valid = isA1ItemValid();
        super.postCalucate();
    }
}

public   class ItemB extends BaseItem {
    Integer size;

    @Override
    public void postCalucate() {
        //some B specific calculations
        super.postCalucate();
    }
}

有没有更好的方法/模式来完成我的任务?有什么建议吗


共 (3) 个答案

  1. # 1 楼答案

    您尝试使用的模式相当合理。一般来说,我可能会建议使用接口而不是BaseItem类,因为它可能不包含那么多公共功能

    一般来说,大多数人似乎建议为类定义要实现的接口。如果您确实希望在抽象类中共享公共代码,我建议该类实现该接口,因为这种模式将在将来提供更大的可扩展性和灵活性

    因此,您首先要定义对您来说是什么。对我来说,在您的用例中,一个项似乎是三件事:第一,它必须定义将对所有项调用的postCalculate()方法。其次,它必须提供一个isValid()方法。第三,它还应该提供getName()方法

    public interface Item {
        void postCalucate();
        boolean isValid();
        String getName();
    }
    

    然后开始实现抽象类。仅当确实需要在所有项目之间共享代码库时才执行此操作

    public abstract class BaseItem implements Item {
        String name;
        boolean valid = true;
    
        public void postCalucate() {
            //common calculation
            valid = valid && (name != null);
        }
    
        public boolean isValid() { 
            return valid; 
        }
    
        public String getName() {
            return name;
        }
    }
    

    如果是BaseItem。postCalculate()是所有项目都需要执行的操作,这是一个很好的方法。如果您不能完全确定,那么最好在HelperTool类中的某个地方定义一个方法,该方法对项执行此通用计算,并由postCalculate()方法调用:

    public class ItemTools {
        public static boolean meetsRequirements(Item item) {
            return item.isValid && item.getName() != null;
        } 
    }
    

    许多人会争辩说,这给了你一个更容易的时间,因为你对BaseItem的需求可能会随着时间的推移而改变

    无论您选择哪条路线,现在您只需定义实际项目:

    public   class ItemA extends BaseItem {
        BigDecimal value;
    
        @Override
        public void postCalucate() {
            //some A specific calculations                        
            super.postCalucate();
        }
    }
    
  2. # 2 楼答案

    虽然一般的建议是避免过度使用继承,但这不是过度使用的情况。因此,继续采用这种方法

    除此之外:您的代码显示了封装问题。你不应该拥有所有这些非私人领域。作为提醒:no可见性就是包可见性(在整个包和所有子类中可见)。让你的领域成为私人领域

  3. # 3 楼答案

    你的建议似乎是合理的

    但可以肯定的是,您必须查看对象生命周期中的所有事件:

    • 实例化
    • 使用,阅读
    • 协作
    • 坚持