Java 避免重复代码的好策略

Java 避免重复代码的好策略,java,oop,design-patterns,Java,Oop,Design Patterns,假设我有以下场景: public class A { public String createString(final String value){ if (value == null){ throw new NullPointerException("value must NOT be null."); } final StringBuffer sb = new StringBuffer(); s

假设我有以下场景:

public class A {
    public String createString(final String value){
        if (value ==  null){
            throw new NullPointerException("value must NOT be null.");
        }
        final StringBuffer sb = new StringBuffer();
        sb.append("A");
        sb.append("B");
        sb.append("C");
        if (value.length() > 3){
            sb.append("D");
            sb.append("E");
        }
        sb.append("Z");
        return sb.toString();   
    }
}
和另一个应该做类似任务的类:

public class B {
    public String createString(final String value){
        if (value ==  null){
            throw new NullPointerException("value must NOT be null.");
        }
        final StringBuffer sb = new StringBuffer();
        sb.append("A");
        sb.append("B");
        sb.append("C");
        sb.append("Z");
        return sb.toString();   
    }
}
避免重复代码的好策略是什么?到目前为止,我想到的是类B具有a的子集功能,因此应该从类a扩展而来,相同的任务应该重构为受保护的方法(假设它们在同一个包中)。这就是它的样子:

public class A {
    public String createString(final String value){
        final StringBuffer sb = createTheFirstPart(value);
        if (value.length() > 3){
            sb.append("D");
            sb.append("E");
        }
        createTheLastPart(sb);
        return sb.toString();   
    }

    protected void createTheLastPart(final StringBuffer sb) {
        sb.append("Z");
    }

    protected StringBuffer createTheFirstPart(final String value) {
        if (value ==  null){
            throw new NullPointerException("value must NOT be null.");
        }
        final StringBuffer sb = new StringBuffer();
        sb.append("A");
        sb.append("B");
        sb.append("C");
        return sb;
    }
}
B类:

public class B extends A {
    public String createString(final String value){
        final StringBuffer sb = createTheFirstPart(value);
        createTheLastPart(sb);
        return sb.toString();   
    }
}
另一种可能的解决方案如下:

public class A {
    public String createString(final String value){
        if (value ==  null){
            throw new NullPointerException("value must NOT be null.");
        }
        final StringBuffer sb = new StringBuffer();
        sb.append("A");
        sb.append("B");
        sb.append("C");
        addSomeSpecialThings(value, sb);
        sb.append("Z");
        return sb.toString();   
    }

    protected void addSomeSpecialThings(final String value, final StringBuffer sb) {
        if (value.length() > 3){
            sb.append("D");
            sb.append("E");
        }
    }
}
B类:

public class B extends A {
    public String createString(final String value){
        return super.createString(value);
    }

    protected void addSomeSpecialThings(final String value, final StringBuffer sb) {
        // do nothing
    }
}
显然这不是很好,因为B有一个空的impl。增加一些特别的东西。 这个例子也很简单。例如,方法中可能存在更多差异,因此提取相同的功能就不那么容易了

我的解决方案都是关于继承的,也许用组合来实现这一点会更好。我还认为这可能是战略模式的一个重要方面

那么,解决此类问题的最佳方法是什么?提前感谢您的帮助


kuku.

我将把共享代码放在a和B的超类中:

public abstract class SomeName {
    public final String createString(final String value){
        if (value ==  null){
            throw new NullPointerException("value must NOT be null.");
        }
        final StringBuffer sb = new StringBuffer();
        sb.append("A");
        sb.append("B");
        sb.append("C");
        addSomeSpecialThings(value, sb);
        sb.append("Z");
        return sb.toString();   
    }

    protected abstract void addSomeSpecialThings(final String value,
            final StringBuffer sb);
}
那么B看起来像这样:

public class B extends SomeName {
    protected void addSomeSpecialThings(final String value,
            final StringBuffer sb) {}
}
这将是一个:

public class A extends SomeName {
    protected void addSomeSpecialThings(final String value, final StringBuffer sb) {
        if (value.length() > 3){
            sb.append("D");
            sb.append("E");
        }
    }
}

所描述的情况相当简单。我认为继承在这里是可以的,但我建议创建一个带有空实现的addSomeSpecialThings的基类,然后继承两个类a和B,并重写该方法


战略模式是合适的,但不是在这样简单的情况下。有两种情况对于实现模式所需的开销来说太少了。

以牺牲可读性为代价在这样简单的代码中进行分解是没有意义的。组合与继承的选择只会与更现实的例子有关,而且也更明显。

hm。。是的,这是一个非常简单的例子,但我认为即使在这里也应该避免重复代码。当我必须决定组合与继承时,我只会问一个基本问题:这真的是一种“是-是”关系吗。大多数情况下,答案是显而易见的。所有重复都是从简单开始的,然后当开发人员找这样的借口,而不是遵循适当的工程实践时,它就会变成一个复杂的混乱。这是一个很好的建议,谢谢。但是我不喜欢空的impl,我的问题是空的impl。这是我试图避免的。@kukudas:然后在超类中使该方法为空,并在B中省略它。