2012-02-20 4 views
7

특정 속성이 null이 아닌 경우에만 arrayList에 객체 컬렉션을 추가하고 싶습니다.null이 아닌 속성을 추가하려면 ArrayList를 확장해야합니까?

나는 ArrayList를 확장하고 자식 클래스 내부에서 검사를 구현할 생각이다.

하나의 다른 방법은 속성을 Arraylist에 넣기 전에 확인하는 것입니다.하지만 이는 논리를 기반으로 arraylist에 객체를 추가해야하는 경우 if check마다 분산시켜야합니다. .

나는 그것에 대한 당신의 생각을 알고 싶습니다 ... 두 번째 생각은 과잉입니까?

답변

20

데코레이터 패턴

사실은 잘 문서화 Decorator 패턴을 사용하여 ArrayList 포장 추천 할 것입니다. 당신은 단순히 포장하여 위임 방법 중 가장 그러나이 유효성 검사 논리 추가 다른 List 구현 ArrayList :

public class ValidatingListDecorator extends AbstractList<MyBusinessObject> 
{ 

    private final List<MyBusinessObject> target; 

    public ValidatingListDecorator(List<MyBusinessObject> target) { 
     this.target = target; 
    } 

    @Override 
    public MyBusinessObject set(int index, MyBusinessObject element) 
    { 
     validate(element); 
     return target.set(index, element); 
    } 

    @Override 
    public boolean add(MyBusinessObject o) 
    { 
     validate(o); 
     return target.add(o); 
    } 

    //few more to implement 

} 

장점 : 당신이 원하는 경우

  • 당신은 아직 검증하지 않고 원료 목록에 액세스 할 수 있습니다 (하지만 당신이 할 수있는 이 제한)
  • 다른 유효성 검사를 쉽게 쌓아 올리려면 선택 사항을 켜고 끕니다. @helios
  • 에서 언급 한 바와 같이
  • 특정 List 구현을 묶어하지 않습니다 테스트 용이성
  • 을 향상 composition over inheritance 촉진, 당신은 LinkedList에 유효성 검사를 추가하거나 Hibernate 영구 목록을 -backed. 모든 컬렉션의 유효성을 검사하기 위해 일반 Collection 데코레이터를 생각해 볼 수도 있습니다.

구현 구현에도 불구하고

을 기억 노트 당신에 대해 기억해야 할 방법을 꽤 많이 있습니다 오버라이드 (override) 동안 (?) 또한 당신의 add(), addAll(), set(), subList()을 등

객체는 변경 불가능해야합니다. 그렇지 않으면 유효한 객체를 추가/설정하고 이후에 수정하여 계약을 위반할 수 있습니다.

좋은 OO 디자인은 마침내 나는 썼다 :

validate(element) 

하지만 고려 : 더 나은 디자인입니다

element.validate() 

합니다.

스태킹 검증 단일, 별도의 클래스에 각하게 proprty/apsect를 검증, 검증 스택하려는 경우, 다음과 같은 관용구 고려하기 전에 언급 한 바와 같이

:

public abstract class ValidatingListDecorator extends AbstractList<MyBusinessObject> 
{ 

    private final List<MyBusinessObject> target; 

    public ValidatingListDecorator(List<MyBusinessObject> target) { 
     this.target = target; 
    } 

    @Override 
    public MyBusinessObject set(int index, MyBusinessObject element) 
    { 
     validate(element); 
     return target.set(index, element); 
    } 

    protected abstract void validate(MyBusinessObject element); 

} 

을 ... 그리고 몇 구현 :

class FooValidatingDecorator extends ValidatingListDecorator { 

    public FooValidatingDecorator(List<MyBusinessObject> target) 
    { 
     super(target); 
    } 

    @Override 
    protected void validate(MyBusinessObject element) 
    { 
     //throw if "foo" not met 
    } 
} 

class BarValidatingDecorator extends ValidatingListDecorator { 

    public BarValidatingDecorator(List<MyBusinessObject> target) 
    { 
     super(target); 
    } 

    @Override 
    protected void validate(MyBusinessObject element) 
    { 
     //throw if "bar" not met 
    } 
} 

foo는을 확인하고 싶으십니까?

List<MyBusinessObject> list = new FooValidatingDecorator(rawArrayList); 

foo는 모두를 확인하고 싶으십니까?

List<MyBusinessObject> list = 
    new BarValidatingDecorator(new FooValidatingDecorator(rawArrayList)); 
+6

+1 상속 이상의 구성! – helios

+0

+1 많은 답변을 주셔서 감사합니다. – Sudhakar

1

당신이 이것을 시행하기를 원한다면 (왜 성공했는지 확인하기 위해 추가 할 때마다 add 메소드의 반환 값을 확인해야하지만) 그렇지 못하다.

이것은 나중에 반복되는 소프트웨어 반복에서 유착되거나 겹쳐지지 않을 수있는 중복 논리를 제거하는 좋은 방법입니다.

+0

나는 동의하지만 특정 목록 구현에서 확장 할 때 IMO에는 하나의 절충점이 있습니다. 다른 전략으로 전환 할 수 없습니다. ArrayList를 LinkedList로 대체하십시오. 위임은 또 다른 선택 사항입니다. – home

+0

@home 일종의, arraylist를 확장하는 것이 인터페이스가 정확히 같거나 다소 가까운 한 다른 것을 확장하는 것으로 전환하는 것은 쉽습니다. –

+0

다시 동의합니다. +1 – home

0

이 코드를 다시 사용하고 ArrayList 클래스를 오버라이드 한 것을 기억하지 못하는 경우에만 철저히 설명해야합니다.

1

저는 이것이 좋은 습관이라고 생각하지 않습니다. Util-Class를 Util-Class에 두 개의 매개 변수를 사용하여 작성하는 것을 고려하십시오 : 배열 목록과 추가하려는 객체. 여기서 원하는 것을 확인할 수 있고 코드 전체에서 로직을 재사용 할 수 있습니다.

관련 문제