2012-02-20 35 views
7

我想添加一個對象的集合到一個arrayList,只有當這個特定的屬性不是null的時候。我應該擴展ArrayList以添加非空的屬性嗎?

我在考慮擴展ArrayList並在子類中執行檢查。

另一種方法是在將屬性放入Arraylist之前檢查屬性,但這意味着,如果需要將對象添加到基於邏輯的陣列列表中,我將不得不分散if檢查每個位置。

我想知道你的想法...第二個想法是矯枉過正?

回答

20

Decorator模式

我真的建議使用證據充分的Decorator圖案包裹ArrayList。你只需換你ArrayList與另一List實現,它代表大多數的方法,但增加了驗證邏輯:

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 

} 

優點:

  • 您仍然可以訪問未經驗證的原始列表,如果你想要的(但你可以限制這個)
  • 更容易堆疊不同的驗證,有選擇地打開和關閉它們。
  • 促進composition over inheritance@helios
  • 注意提高可測試性
  • 不配合你到一個特定的List實現,可以添加驗證LinkedListHibernate -backed持續名單。你甚至可以考慮通用Collection修飾器來驗證任何集合。

實現說明

儘管實施記得有相當多的方法,你必須要記住,同時覆蓋:(?)add()addAll()set()subList()

而且你對象必須是不可變的,否則用戶可以添加/設置有效的對象並修改它以後違反合同。

良好的面向對象設計

Finaly我寫道:

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

想,只確認

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

想驗證這兩個酒吧

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

對於繼承組合而言+1! – helios 2012-02-20 09:40:41

+0

+1感謝您的詳細回覆 – Sudhakar 2012-02-20 10:38:49

1

如果您想強制執行此操作,我不明白爲什麼不這樣做(儘管您應該在添加以確保成功時檢查add方法的返回值)。

這是擺脫冗餘邏輯的一種好方法,它可能會或可能不會在後面的軟件迭代中出現。

+0

我同意你的看法,但IMO在從某個列表實現延伸時有一個權衡 - 不可能切換到不同的策略,例如,用LinkedList替換ArrayList。代表團將是另一種選擇。 – home 2012-02-20 09:39:11

+0

@home排序,只要接口完全相同或稍微接近,就可以很容易地將一些將arraylist擴展到某些擴展其他東西的東西。 – 2012-02-20 09:40:43

+0

再次同意。 +1 – home 2012-02-20 09:41:49

0

唯一的問題是如果你去重用這段代碼,你不記得你已經覆蓋了ArrayList類,請確保徹底地評論。

1

我不認爲這是一個很好的做法。請考慮在具有兩個參數的Util-Class中編寫一個Util-Method:您想要添加的數組列表和對象。在那裏你可以檢查你想要的任何東西,並且可以在你的代碼中重複使用邏輯。

相關問題