2012-02-20 25 views
7

特定の属性がnullでない場合にのみ、オブジェクトのコレクションをarrayListに追加したいとします。nullでない属性を追加するためにArrayListを拡張する必要がありますか?

私は、ArrayListを拡張し、子クラスの中でチェックを実装することを考えています。

一つの代替方法は、Arraylistに入れる前にその属性をチェックすることですが、ロジックに基づいてオブジェクトをarraylistに追加する必要がある場合は、ifチェックをすべて分散する必要があります。

私はあなたの考えを知っています...もう一度考えると、それは過剰ですか?

答えて

20

Decoratorパターン

私は実際によく文書Decoratorパターンを使用して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 

} 

利点:

  • したい場合は、まだ検証せずに生のリストにアクセスすることができます(ただし、あなたができるあなたは、単にデリゲートがメソッドのほとんどが、検証ロジックを追加することを別のListの実装を使用してArrayListを包みますこれを制限する)
  • 異なるバリデーションを積み重ねることが容易になるように、それらを選択的にオン/オフします。
  • @helios
  • で述べたようにcomposition over inheritanceを促進するテスト容易性
  • が特定List実装にあなたを結ぶません、あなたはLinkedListまたはHibernate永続的なリストを-backedに検証を追加することができます向上させます。すべてのコレクションを検証するために、汎用のCollectionデコレータについて考えることもできます。

実装は実装にもかかわらず

ノートオーバーライドしながら、あなたがについて覚えている方法のかなり多くがあります覚えている:(?)subList()add()addAll()set()を、など

また、あなたのオブジェクトは不変でなければならず、さもなければ、ユーザは有効なオブジェクトを追加/設定し、後でそれを変更して契約に違反することができる。

グッドOO設計

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

のみFOOを検証したいですか?

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

は両方FOOバーを検証したいですか?別の戦略に切り替えることはできません、例えば - 私はあなたと同意するが、IMO 1つのトレードオフの特定のリストの実装から延びるあり

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

+1の継承を超える構成! – helios

+0

+1詳細な返信をありがとう – Sudhakar

1

これを実行したいのであれば、私はなぜそうは思わないのですか(ただし、addメソッドを実行するときに必ずaddメソッドの戻り値をチェックしてください)。

これは、後のソフトウェアの繰り返しでは冗長ロジックを取り除くための良い方法です。

+0

ArrayListをLinkedListに置き換えます。委任が別の選択肢になります。 – home

+0

@home arraylistを拡張するものを、インタフェースがまったく同じかまたは多少近いものに拡張するものに切り替えるだけで十分です。 –

+0

再度、同意します。 +1 – home

0

このコードを再利用し、ArrayListクラスをオーバーライドしたことを覚えていない場合は、完全にコメントしてください。

1

私はこれが良い習慣だとは思わない。 Util-ClassにUtil-Methodを書くには、配列リストと追加したいオブジェクトの2つのパラメータをとります。そこでは、あなたが望むものをチェックして、あなたのコード全体でロジックを再利用することができます。

関連する問題