2011-02-04 2 views
3

私は多くのメソッドを持っています(この場合、Webサービスからのものですが、これは影響ありません)。彼らはすでにの固定リリースバージョンであり、変更されません、それは私に適応することです。私は既に私のプロジェクトにプロキシーを持っていますが、実際には私はすでにそれを呼び出しています。プロジェクトは大丈夫です。同様の機能を実行する異なるクラス(異なるメソッドとタイプ)を呼び出すことができますか?

このクラスのメインメソッドは、いくつかの入力パラメータ(トランザクションタイプ、およびトランザクションデータを含むXML文字列)を取得します。 TransactionTypeに基づいて、どのクラスとメソッドを呼び出すべきかを知っています。また、提供されたXMLから既に構築された、期待される型変数を提供する必要があります。ここでは、およそ、(私は右ここにコードを持っているので、構文エラーのための私を許していない)それが今日である方法は次のとおりです。

public class MyClass() 
{ 
    public void MyMethod(string TransactionType, string XML) 
    { 
    switch(TransactionType) { 
     case "1": 
     type1VO type1Object = (new Deserializer<Type1>()).XML2Object(XML); 
     ws = new WSProxy1(); 
     string response = ws.Method1(type1VO); 
     // 
     // lots of other lines of code that use type1VO, type1Object, the response, etc. 
     // 
     break; 
     case "2": 
     type2VO type2Object = (new Deserializer<Type2>()).XML2Object(XML); 
     ws = new WSProxy2(); 
     string response = ws.Method2(type2VO); 
     // 
     // same structure here, but handling types specific for "case 2" 
     // 
     break; 
    } 
    ... 
    } 
} 

そして、それは延々と続きます。今日、このコードはすでに15種類のトランザクションタイプを処理していますが、上記の方法で開発されました。私はこれを変更しようとしているので(他のシステムにはこのロジックが必要なので、このコードを自分自身のライブラリに移動します)、コードの改良によって利益を得ることができると思いました。また、上記のコードはかなり減少しています。各ケースの特定の型を扱う行が増えています。例を挙げました。

私はそれほど心配していませんが、私にはそれほどエレガントではないようです。何らかのデザインパターンがこれを処理できるという印象を与え、トランザクションタイプごとに繰り返すのではなく、1つのブロックでトランザクションを処理できるという印象を与えました。たぶん私は間違っていて、これはできません、私はちょうどそれを繰り返しコードを見て "感じた"。

.NET v2.0ではC#ですが、他のバージョンや言語に関する回答がある場合は気になりません。私は関与している概念についてもっと気にしています。私はあなたが提供できるヒントについて皆様に感謝しています。彼らはいつも素晴らしいです。

答えて

1

Adapter PatternStrategy Patternを組み合わせて試すことができます。

メソッドを呼び出すインターフェイスを作成し、このインターフェイスをサポートするプロキシごとにアダプタを作成します。アダプタは、適応しているオブジェクトに固有の動作をカプセル化する必要があります。実行時に切り替えを可能にするためにサポートされているトランザクションタイプをインタフェースに返すようにすることもできます。

例は次のようになります。ヒントの

public interface IExecuteStrategy 
{ 
    string TransactionType {get;} 
    void Execute(string xmlData); 
} 

public class WsProxy1Adapter : IExecuteStrategy 
{ 
    public string TransactionType 
    { 
     get { return "1"; } 
    } 

    public void Execute(string xmlData) 
    { 
     Type1 type1Object = (new Deserializer<Type1>()).XML2Object(XML); 
     var ws = new WSProxy1(); 
     string response = ws.Method1(type1Object); 
     // 
     // lots of other lines of code that use type1VO, type1Object, the response, etc. 
     // 
    } 
} 

public class WsProxy2Adapter : IExecuteStrategy 
{ 
    public string TransactionType 
    { 
     get { return "2"; } 
    } 

    public void Execute(string xmlData) 
    { 
     Type2 type2Object = (new Deserializer<Type2>()).XML2Object(XML); 
     var ws = new WSProxy2(); 
     string response = ws.Method1(type2Object); 
     // 
     // lots of other lines of code that use type1VO, type1Object, the response, etc. 
     // 
    } 
} 

public class MyClass 
{ 
    private static Dictionary<string, IExecuteStrategy> _transactionHandlers; 

    static MyClass() 
    { 
     _transactionHandlers = new Dictionary<string,IExecuteStrategy>(); 

     IExecuteStrategy obj = new WsProxy1Adapter(); 
     _transactionHandlers.Add(obj.TransactionType, obj); 

     obj = new WsProxy2Adapter(); 
     _transactionHandlers.Add(obj.TransactionType, obj); 
    } 


    public void MyMethod(string TransactionType, string XML) 
    { 
     _transactionHandlers[TransactionType].Execute(XML); 
    } 
} 
+0

これはヒントのおかげで、かなり上品なデザインです。各ケースのコードを特定のアダプタに転送するので、メインの実行に単一のブロックを使用する意向はまだありません。それは確かであり、確かに、それぞれのコードに1つのメインブロックを達成する方法がない場合、おそらくそれは私がやる方法です。ありがとう、たくさんの人、それは素敵なアプローチでした。 –

+1

@Charlie Brown:OK、gotcha - 私はあなたが長いswitch文からリファクタリングコードを探していると思った。すべての呼び出しに1つのコードブロックを使用する方法がわかりません。おそらくそれはいくつかの複雑な反射で行うことができます - しかし、それは努力の価値があるかどうかわかりません... – blech

+0

そうではありません。あなたのアプローチを使いました。ここの事実は、基本サービスがより良い方法で設計されているはずであるということです。 –

1

トランザクションタイプの基本的な流れを理解する抽象クラスを作成する必要があります。次に、型固有のコードを埋め込む各トランザクションタイプの子クラスを作成します。これは、あなたが与えたコードに基づいて、あなたのベースクラスに開始することができます

abstract class Base<T, U> 
{ 
    private U _obj; 
    public Base(string xml) 
    { 
    _obj = (new Deserializer<T>()).XML2Object(xml); 
    } 

    public abstract void process(); 
    protected abstract String getResponse(); 
} 

そして、トランザクション・タイプに基づいて正しい子クラスを返すために、単純な工場を作ります。これにより、大文字のステートメントが次のようなものになります。

public void MyMethod(string transactionType, string xml) 
{ 
    Base.getByTransactionType(transactionType).process(); 
} 
+0

おかげで、バディ。私はこれに近いものを使ってみましたが、子クラスでコードを繰り返さなければならないという事実にはまだ悩まされました。多分、時には "マジック"がなく、あなたがそれを受け入れる必要があるのですが、これはこれらのケースの1つかもしれないと思います。もう一度、非常にシンプルで効果的なフォーマットに感謝します! –

+0

あなたがまだコードを繰り返していることがわかった場合、それは基本クラスに引き込まれる可能性がさらに高いことを意味します。共通点を見つけてそれを利用するのは問題です。 – unholysampler

関連する問題