2009-07-08 5 views
6

ハードウェアの構成を表すオブジェクトがあるとします。議論のために、温度コントローラ(TempController)。 1つのプロパティ、設定温度が含まれています。モデルとその表現を分離するオブジェクト指向の方法

他のデバイスで使用するために、この設定をファイルに保存する必要があります。ファイル形式(FormatA)は石で設定されています。私は、TempControllerオブジェクトにファイル形式について知りたがりません...そのオブジェクトには関係ありません。そこで私は別のオブジェクト "FormatAExporter"を作成し、TempControllerを望ましい出力に変換します。

1年後、私たちは新しい温度コントローラーを作りました。これは「AdvancedTempController」と呼ばせましょう。セットポイントだけでなく、1つまたは2つ以上のプロパティーを意味するレートコントロールも備えています。これらのプロパティを保存するために、新しいファイル形式も発明されています。それをFormatBとしましょう。

両方のファイル形式が両方のデバイスを表すことができます(設定が不足している場合、AdvancedTempControllerには適切なデフォルト値が設定されているものとします)。

ここに問題があります:私が持っているオブジェクトのタイプを理解するために 'isa'やその他の不正な方法を使用しないと、FormatBExporterはどのように両方のケースを処理できますか?

私の最初の本能は、TempController.getExporter()とAdvancedTempController.getExporter()のように、そのクラスの顧客エクスポータを提供できるメソッドを各温度コントローラに持たせることです。これは、複数のファイル形式をうまくサポートしません。

唯一の考え方は、各温度コントローラにプロパティとその値のリストを返すメソッドを持たせてから、フォーマッタがそれらの出力方法を決定できることです。それはうまくいくだろうが、それは畳み込まれているようだ。

更新:今後の作業では、後者のアプローチは実際にうまく機能しません。あなたのすべての型がシンプルな場合は、プロパティがオブジェクトの場合、レベルを下げて問題をプッシュするだけです...あなたはString、Object値のペアを返さなければならず、エクスポータは何を知る必要がありますオブジェクトは実際にそれらを利用することです。だから、問題を別のレベルにプッシュするだけです。

これをどのように柔軟に保つための提案はありますか?

答えて

4

あなたができることは、汎用アーカイバを使用してTempController自体を持続させることです。このようにそれを維持することにより

class TempController 
{ 
    private Temperature _setPoint; 
    public Temperature SetPoint { get; set;} 

    public ImportFrom(Archive archive) 
    { 
     SetPoint = archive.Read("SetPoint"); 
    } 
    public ExportTo(Archive archive) 

    { 
     archive.Write("SetPoint", SetPoint); 
    } 
} 

class AdvancedTempController 
{ 
    private Temperature _setPoint; 
    private Rate _rateControl; 
    public Temperature SetPoint { get; set;} 
    public Rate RateControl { get; set;} 

    public ImportFrom(Archive archive) 
    { 
     SetPoint = archive.Read("SetPoint"); 
     RateControl = archive.ReadWithDefault("RateControl", Rate.Zero); 
    } 

    public ExportTo(Archive archive) 
    { 
     archive.Write("SetPoint", SetPoint); 
     archive.Write("RateControl", RateControl); 
    } 
} 

、コントローラは、実際の値が格納されているか気にしませんが、あなたはまだよくカプセル化されたオブジェクトの内部を維持しています。

すべてのアーカイブクラスが実装できる抽象的なアーカイブクラスを定義できます。

abstract class Archive 
{ 
    public abstract object Read(string key); 
    public abstract object ReadWithDefault(string key, object defaultValue); 
    public abstract void Write(string key); 
} 

フォーマットAアーカイバは片方向、フォーマットBアーカイブは別のことができます。

class FormatAArchive : Archive 
{ 
    public object Read(string key) 
    { 
     // read stuff 
    } 

    public object ReadWithDefault(string key, object defaultValue) 
    { 
     // if store contains key, read stuff 
     // else return default value 
    } 

    public void Write(string key) 
    { 
     // write stuff 
    } 
} 

class FormatBArchive : Archive 
{ 
    public object Read(string key) 
    { 
     // read stuff 
    } 

    public object ReadWithDefault(string key, object defaultValue) 
    { 
     // if store contains key, read stuff 
     // else return default value 
    } 

    public void Write(string key) 
    { 
     // write stuff 
    } 
} 

別のコントローラタイプを追加して、それをどのフォーマッタにも渡すことができます。別のフォーマッタを作成し、それをコントローラに渡すこともできます。あなたがこれを行うことができますC#またはこれをサポートする他の言語で

+0

を適用する場所だと思います共同作業者をモックする。 –

+0

これは、私が計画していたよりも手の込んだ感じですが、私はそれが好きです。これは、リスト内のすべてのプロパティを返す柔軟性を提供しますが、インターフェイス全体で型情報を保持します。そして、それは確かにテスト容易性に役立ちます。 –

0

私はgetStateメソッドを使って "temp controller"を持っています(例えば、Pythonのdict、Javascriptのオブジェクト、C++のstd :: mapやstd :: hashmapなどのマップを返します。 )のプロパティと現在の値 - それについて巻き込まれて何ですか?ほとんどシンプルではなく、完全に拡張可能で、使用することから完全に切り離されています(表示、シリアライズ、& c)。

0

FormatBExporterがAdvancedTempControllerを使用する場合、TempControllerをAdvancedTempControllerに準拠させるブリッジクラスを作成できます。あなたはAdvancedTempControllerに何らかの種類のgetFormat()関数を追加する必要があるかもしれません。例えば

FormatBExporter exporterB; 
TempController tempController; 
AdvancedTempController bridged = TempToAdvancedTempBridge(tempController); 

exporterB.export(bridged); 

キーと値のマッピング方式を使用するオプションもあります。 FormatAExporterは、キー "setpoint"の値をエクスポート/インポートします。 FormatBExporterは、キー "setpoint"と "ratecontrol"の値をエクスポート/インポートします。このように古いFormatAExporterは新しいファイル形式( "ratecontrol"は無視されます)を読み込み、FormatBExporterは古いファイル形式を読み取ることができます( "ratecontrol"がない場合はデフォルトを使用します)。

0

さて、多くのことは、あなたが話しているファイル形式に依存します。

キー/値の組み合わせ(xmlなどのネストされたものを含む)に基づいている場合、適切なファイル形式の作家でスローすることができる緩やかに型付けされた何らかの種類の中間メモリオブジェクトを持つことは、それ。

そうでなければ、各シナリオにカスタムロジックを使用して、オブジェクトとファイル形式の4つの組み合わせがあるシナリオがあります。その場合、どちらのコントローラーも処理できるファイル形式ごとに単一の表現を持つことは不可能かもしれません。つまり、ファイル形式のライターを一般化できない場合は、一般化できません。

私は、輸出業者を持つコントローラのアイデアはあまり好きではありません - 私は、ストレージメカニズムやその他のものについて知っているオブジェクトのファンではありません(彼らはストレージの概念について知っているかもしれません。それらはいくつかのDI機構を介して)。しかし、私はあなたがそれに同意していると思います。

0

オブジェクト指向モデルでは、集合体としてのオブジェクトメソッドがコントローラです。あなたのプログラムをMとVに分けて、OOを使ってプログラミングしているのであれば、Cをそれほど必要としません。

1

class TempController { 
    int SetPoint; 
} 
class AdvancedTempController : TempController { 
    int Rate; 
} 

class FormatAExporter { 
    void Export(TempController tc) { 
     Write(tc.SetPoint); 
    } 
} 

class FormatBExporter { 
    void Export(TempController tc) { 
     if (tc is AdvancedTempController) { 
      Write((tc as AdvancedTempController).Rate); 
     } 
     Write(tc.SetPoint); 
    } 
} 
+1

これは短期的には最も簡単な方法です。しかし、touは 'is'と 'as'を使用しました。これで、FormatBExporterを毎回維持して、さまざまな種類のすべてを処理する必要があります。極端に言えば、タイプが何であるか把握するために「if」ステートメントの森林があります。これらのタイプのポイントは、このようなことを自分自身で行うことでした。 –

0

私は、これはFactory method patternがはるかに簡単にので、これはまたので、コードをよりテスト可能にする

関連する問題