2010-11-27 6 views
12

내가 다음과 같은 시나리오를 가지고 말할 수 있습니다 중복 코드를 피하기 위해를 방지 할 수있는 좋은 전략이 될 것입니다 무엇 좋은 전략은

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(); 
    } 
} 

중복 코드? 내가 지금까지 생각해 낸 점은 A의 하위 집합 기능을 갖고 따라서 A 클래스에서 확장해야하는 B 클래스와 동일한 작업이 동일한 패키지에 있다고 가정 할 때 보호 된 메서드로 리팩토링되어야한다는 것입니다.

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 
    } 
} 

분명히 thi B는 빈 impl를 가지고 있기 때문에 s는 그렇게 좋지 않습니다. addSomeSpecialThings 중 하나입니다. 또한이 샘플은 매우 간단한 샘플입니다. 예를 들어 메서드 내에서 더 많은 차이가있을 수 있으므로 동일한 기능을 추출하기가 쉽지 않습니다.

내 솔루션은 모두 상속에 관한 것일 수 있습니다. 구성을 통해이를 수행하는 것이 더 나을 수도 있습니다. 나는 이것이 아마도 전략 패턴의 수위 (canidate)라고 생각했다.

그런 종류의 문제에 대한 최선의 접근 방법은 무엇입니까? 모든 도움을 미리 감사드립니다.

쿠쿠.

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는 다음과 같이 보일 것이다 :

답변

9

나는 A A의 슈퍼 클래스와 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"); 
     } 
    } 
} 
+0

내 문제는 빈 impl입니다. 나는 피하려고 노력한다. – kukudas

+1

@kukudas : 그런 다음 수퍼 클래스에서 메소드를 비워두고 B에서 생략합니다. – thejh

2

설명 된 상황은 다소 간단합니다. 생각 상속 여기서 괜찮아요,하지만 빈 구현 된 addSomeSpecialThings, 기본 클래스를 만들고 두 클래스 A 및 B 상속하고 메서드를 재정의 할 것이 좋습니다.

전략 패턴이 적절하지만 단순한 경우는 아닙니다. 두 가지 상황은 패턴을 구현하는 데 필요한 오버 헤드가 너무 적습니다.

+0

Thats 좋은 제안 감사. 그러나 나는 빈 impl를 좋아하지 않는다. – kukudas

1

가독성을 희생하여 이러한 간단한 코드에 인수 분해 할 필요는 없습니다. 컴포지션과 상속 선택은보다 현실적인 예와 관련해서 만 중요 할뿐 아니라 더 분명합니다.

+0

흠 .. 네, 아주 간단한 예입니다.하지만 여기서도 중복 된 코드는 피해야한다고 생각합니다. – kukudas

+1

컴포지션과 상속에 대해 결정해야 할 때 나는 기본적인 질문을한다 : 이것은 정말로 "is-a"관계인가? 대부분의 경우 대답은 명백합니다. – neurolabs

+2

모든 복제가 단순 해지기 시작합니다. 그런 다음 devs가 적절한 엔지니어링 기법을 따르는 대신 이러한 변명을하면 복잡한 혼란에 빠지게됩니다. – jeremyjjbrown

관련 문제