2012-01-12 22 views
2

アダプターのクラスについてはほとんど疑いがありません。私はアダプタクラスの目標を知っています。そしていつ使うべきか。私の疑問は、クラスの建設についてです。私はいくつかのチュートリアルをチェックして、それらのすべては私が "アダプター"への依存として "Adaptee"クラスを渡すべきだと言います。例: アダプターのパターンと依存性

Class SampleAdapter implements MyInterface 
{ 
    private AdapteeClass mInstance; 
    public SampleAdapter(AdapteeClass instance) 
    { 
     mInstance=instance; 
    } 
} 

この例は、wikipediaからコピーされています。ご覧のように、AdapteeClassは私のオブジェクトに依存として渡されます。問題はなぜですか?オブジェクトのインタフェースを変更している場合は、「新しい」インタフェースを使用することは明らかです。古いインタフェースは必要ありません。なぜ私のアダプタの外に "古い"クラスのインスタンスを作成する必要があります。誰かが私が必要とするものを渡すことができるように依存性注入を使うべきだと言うかもしれませんが、これはアダプターです - 具体的なクラスのインターフェースを変更する必要があります。個人的に私は、コードがより良いと思う。

Class SampleAdapter implements MyInterface 
{ 
    private AdapteeClass mInstance; 
    public SampleAdapter() 
    { 
     mInstance= new AdapteeClass(); 
    } 
} 

あなたの意見は?

+0

私はあなたがデコレータを探していると思います... – dotnetstep

+1

@dotnetstepいいえ、彼が指しているアダプタパターンはデコレータとは異なります。デコレータはインターフェイスを同じに保ちますが、動作を拡張します。アダプタは、予想されるインターフェイスと一致するように既存のクラスのインターフェイスを再作成します。詳細については、http://stackoverflow.com/questions/350404/how-do-the-proxy-decorator-adaptor-and-bridge-patterns-differを確認してください。 –

答えて

7

カップリングを減らし、コードをよりテスト可能にするために、複雑なオブジェクト(クラスがBuilderまたはFactoryの場合を除いて)に関しては、クラス内でnew演算子を常に避けるべきです。クラスメソッドの中にリストやディクショナリや値オブジェクトなどのコースオブジェクトを構築することができます(おそらくクラスメソッドの目的です)

たとえば、AdapteeClassはRemote Proxyです。ユニットテストを使用する場合、ユニットテストでユニットテストを置き換える方法がないため、ユニットテストでは実際のプロキシクラスを使用する必要があります。

最初のアプローチを使用する場合は、ユニットテストを実行するときに、疑似コードをコンストラクタに簡単に挿入して、すべてのコードパスをテストできます。

Googleはこれをより詳細に説明するが、いくつかの重要なポイントであるguide on writing testable codeあります

はないテスト可能なコードの警告サインを

    コンストラクタやフィールド宣言で
  • 新しいキーワード
  • コンストラクタまたはフィールド宣言の静的メソッド呼び出し
  • コンストラクタのフィールド割り当て以外のもの
  • 完全コンストラクタが終了した後に初期化されない
  • オブジェクト(初期化メソッドに注意)
  • 制御フロー(条件又はループロジック)コンストラクタで
  • コードは、コンストラクタの内部ではなく、工場やビルダーを使用して、複雑なオブジェクトグラフの構築を行います
  • 初期化ブロック
+0

私はそれを買わない - あなたは常にクラス内の新しい演算子を避けるべきである(クラスがビルダーかファクトリである場合を除いて)* - 全く新しいオペレータの悪であるという私の答えを読んでください。 ! " - それはここにあるhttp://stackoverflow.com/questions/8690720/factory-design-pattern-and-keyword-new/8693412#8693412 – dantuch

+1

私はクラスとカップリングでは全く新しい演算子を避けることについて同意します。しかし、アダプタの目的は、与えられたクラスのインタフェースを変更することです。つまり、両方のクラスを結合する必要があります。とにかくあなたはモックについて正しいです。 – Ivan

+1

同意します。アダプタの目的は、あるインタフェースを別のインタフェースに適合させることです。建設は別の責任です。アダプタ内でインスタンスを新規作成すると、インターフェイスへのプログラミング機能が失われ、また、adapteeインスタンスの所有権/有効期間も明示的に設定されます。これらは両方とも、他の場所(例えば、DIコンテナ内)で制御される必要があるものである。 –

1

AdapteeClassは、1つ以上の非自明なコンストラクタを有することができ、追加または使用。この場合、同じ柔軟性を持たせるために、すべてをSampleAdapterコンストラクタに複製する必要があります。既に構築されたオブジェクトを渡す方が簡単です。

0

アダプター内のアダプターを作成することが制限されていると思います。何日前に既存のインスタンスを適応させたいのであればどうでしょうか?

正直言っても、もし可能であれば、私は両方をしています。

Class SampleAdapter implements MyInterface 
{ 

    private AdapteeClass mInstance; 

    public SampleAdapter() 
     : base (new AdapteeClass()) 
    { 
    } 

    public SampleAdapter(AdapteeClass instance) 
    { 
     mInstance=instance; 
    } 
}