是否有任何方法或模式来避免这种Java代码重复

时间:2016-10-05 17:47:39

标签: java design-patterns duplicates

您好我想知道是否有一些模式可以避免代码重复,以及在这种情况下是否适用于Java。

public void updateSequence( DN dn, long seq, long countDescriptorId, int mode ) {
    Collection<ResyncNECountSequenceDescriptor> sequencesCollection = 
        sequences.get( dn );
    ResyncNECountSequenceDescriptor neDescSeq = 
        new ResyncNECountSequenceDescriptor( countDescriptorId, seq );
    if ( sequencesCollection != null && sequencesCollection.size() > 0 ) {
        boolean foundSeq = false;
        for ( ResyncNECountSequenceDescriptor sequence : sequencesCollection ) {
            if ( sequence.getCountDescriptorId() == countDescriptorId ) {
                if ( mode == LAST_CREATED_DATFILE_SEQUENCE ) {
                    sequence.setLastCreatedDatfileSequence( seq );
                } else {
                    if ( seq > sequence.getLastCreatedDatfileSequence() ) {
                        seq = 0;
                    }
                    sequence.setNextDatfileToProcessSequence( seq );
                }
                foundSeq = true;
            }
        }
        if ( !foundSeq ) {
            sequencesCollection.add( neDescSeq );
        }
    } else {
        Collection<ResyncNECountSequenceDescriptor> col = new 
            ArrayList<ResyncNECountSequenceDescriptor>();
        col.add( neDescSeq );
        sequences.putIfAbsent( dn, col );
    }
}

在这个方法中,例如,我想摆脱mode参数,而是做两个方法。事情只是改变的是内在的条件和逻辑,但其余的都是相同的。在这种情况下如何避免或最小化代码重复?

1 个答案:

答案 0 :(得分:0)

  • 首先优化可读性。仅在有充分理由的情况下才优化运行时性能。 “过早优化是编程中所有邪恶的根源”
  • 有一个单独的SequenceCollection类,以便您可以将域逻辑推送到它;您可以决定是应该撰写还是继承自ArrayList。为了简单起见(我不知道你们其余的代码)我做了后者。但通常你应该赞成作文而不是干预。
  • 使用带有Lambda的upsert函数来摆脱重复
  • 请勿使用mode等参数。这些是control couplings(这很糟糕)。
  • 将业务逻辑(例如序列号溢出)推送到设置器(Tell, don't Ask
  • 通常将单独理解的功能分解为单独的方法。

结果如下:

private Map<DN, SequenceCollection> sequences;

class SequenceCollection extends ArrayList<ResyncNECountSequenceDescriptor> {
    private static final long serialVersionUID = 1L;

    public void upsert(long countDescriptorId, long seqNumber,
            Consumer<ResyncNECountSequenceDescriptor> updateFunction) {
        Optional<ResyncNECountSequenceDescriptor> sequence = findByCountDescriptorId(countDescriptorId);
        if (sequence.isPresent()) {
            updateFunction.accept(sequence.get());
        } else {
            this.add(new ResyncNECountSequenceDescriptor(countDescriptorId, seqNumber));
        }
    }

    public Optional<ResyncNECountSequenceDescriptor> findByCountDescriptorId(long countDescriptorId) {
        return this.stream() //
                .filter(seq -> seq.getCountDescriptorId() == countDescriptorId) //
                .findAny();
    }
}

class DN {
}

class ResyncNECountSequenceDescriptor {
    private long seqNumber;

    public ResyncNECountSequenceDescriptor(long countDescriptorId, long seq) {
    }

    public long getCountDescriptorId() {
        return 0;
    }

    public void setLastCreatedDatfileSequence(long seq) {
    }

    public long getLastCreatedDatfileSequence() {
        return 0;
    }

    public void setNextDatfileToProcessSequence(long seqNumber) {
        if (seqNumber > getLastCreatedDatfileSequence()) {
            seqNumber = 0;
        }
        this.seqNumber = seqNumber;
    }
}

public void updateLstCreatedSequence(DN dn, long seqNumber, long countDescriptorId) {
    SequenceCollection sequenceCollection = getSequenceCollection(dn);
    sequenceCollection.upsert(countDescriptorId, seqNumber, seq -> seq.setLastCreatedDatfileSequence(seqNumber));
}

private SequenceCollection getSequenceCollection(DN dn) {
    return sequences.computeIfAbsent(dn, k -> new SequenceCollection());
}

public void updateNextSequence(DN dn, long seqNumber, long countDescriptorId) {
    SequenceCollection sequenceCollection = getSequenceCollection(dn);
    sequenceCollection.upsert(countDescriptorId, seqNumber, seq -> seq.setNextDatfileToProcessSequence(seqNumber));
}