ID和EAN继承可能违反Liskov替换原则

时间:2015-02-01 17:28:22

标签: java oop inheritance design-patterns liskov-substitution-principle

我的申请有一个设计问题。

我有一个产品和一个类别。两者都必须有ID。

类别可以包含任何正整数作为ID。 ( - > Id-class)

产品必须具有介于8和8之间的正整数。 13个密码作为ID。 ( - > Ean-class)

因为这是这些类唯一做的事情(创建一个id)和一个带有正确检查的getter / setter。

为了减少代码(DRY),我让Ean从Id继承。但是不会违反Liskov(LSP)?

我的问题:

  1. 我的LSP推理是否正确? 如果是的话:
  2. 我应该通过创建界面来解决它吗? (看起来像重复的代码)还是有其他解决方案?
  3. 提前致谢!

    Identifier.java

    public class Identifier {
    
        private Long id = 1000000000000L;
    
        public Identifier(){
    
        }
    
        public Identifier(Long id){
            setId(id);
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
    }
    

    Ean.java

    public class Ean extends Identifier {
    
        private final static int MIN_AMOUNT_OF_CIPHERS = 8;
    
        private final static int MAX_AMOUNT_OF_CIPHERS = 13;
    
        private final static String ERROR_EAN_LENGTH = "err_ean_length";
    
        public Ean() {
        }
    
        public Ean(Long ean) throws DomainException {
            setEan(ean);
        }
    
        public Long getEan() {
            return getId();
        }
    
        public void setEan(Long ean) throws DomainException {
            if (String.valueOf(ean).length() < MIN_AMOUNT_OF_CIPHERS
                    || String.valueOf(ean).length() > MAX_AMOUNT_OF_CIPHERS) {
                throw new DomainException(ERROR_EAN_LENGTH);
            }
            setId(ean);
    }
    

1 个答案:

答案 0 :(得分:0)

  

我的LSP推理是否正确?

答案:否

看起来任何地方都接受了Id,Ean实例会有效,对吗?这就是LSP的全部意义所在。这是因为Ean是有效身份证的子集。任何Ean都是有效的Id,但相反的情况并非总是如此。

  

我应该通过创建界面来解决它吗? (好像是重复的   代码)还是有其他解决方案吗?

您可以拥有一个界面和两个特定的实现(Id和Ean)。我可能会这样做,因为对我来说没有理由让Ean子类Id。两者都可以实现一个旨在充当标识符单元的单一界面。

修改 继承模型中的问题是,如果调用从父类继承的setId()方法,则Ean实例可能不一致。