避免重复代码的好策略

时间:2010-11-27 10:11:57

标签: 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();
        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。 addSomeSpecialThings。 这个例子也很简单。例如,方法中可能存在更多差异,因此提取相同的功能并不容易。

我的解决方案都是关于继承的,也许用组合做这件事也会更好。我还认为这可能是战略模式的一个因素。

那么这种问题的最佳方法是什么?提前感谢您的帮助。

裤裤。

3 个答案:

答案 0 :(得分:10)

我会将共享代码放在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) {}
}

这将是A:

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

这种简单的代码没有任何重要因素,但会牺牲可读性。组合与继承选择只会与更现实的例子有关,并且也更加明显。