2016-04-29 16 views
0

データを3通り表現できる「アイテム」があります。私はある表現から他の表現のいずれかに、ランタイムコストで変換することができます。私が変換を行うと、私は新しい表現を周りに残したいと思います。データの表現は、コアデータを「変更する」ことなく、他のものに変換することができます。ランタイムコストのために、データの3つの表現を含むクラスが必要です。いつでも、それらの1〜3が有効になります。複数の表現を持つアイテムのC++デザインパターン

実際のところ、ユーザーが何かを求めることができるアクセス方法もあるためです。この何かは、1つ以上の表現から得ることができます。たとえば、表現1の「範囲」と表現2または3の「ボリューム」を得ることができます。

私の解決策は、3つの表現をメンバーデータとして持つクラスを作成することです)。次に、必要な表現を内部的に知っているgetRange()メソッドを作成し、必要に応じて作成します。これは正常に動作し、getメソッドをconstにすることができないという点を除いてすべての問題を解決します。

このソリューションの実際の問題は、内部的に他の表現を作成する可能性があるため、このクラスの「定数」インスタンスでも実際にはconstではないということです。ただし、表現を変更してもコアデータは変更されないため、実際は「定数」です。

このクラスに役立つC++デザインパターンはありますか?助言がありますか?

答えて

3

私の解決策は、3つの表現をメンバーデータとして(そしてそれらが有効かどうかを判断する方法として)クラスを作成することでした。次に、必要な表現を内部的に知っているgetRange()メソッドを作成し、必要に応じて作成します。これはうまく動作し、すべての私の問題を解決するを除いて、getメソッドはconstすることはできません。

これはmutableタイプのまさに目的です! 、まだconstメソッドを持ちながら内部表現を更新表現がmutable属性行うことができるようにするために:あなたは簡単にチェックできるように

struct A { 

    int get_range() const { 
     if (!_repr2.is_valid()) { 
      _repr2 = Repr2(_repr1); // I am in a const method, but still 
            // I can update a mutable attribute 
     } 
     return _repr2.get_range(); 
    }  

private: 
    mutable Repr1 _repr1; 
    mutable Repr2 _repr2; 
}; 

Here表現を格納するためにstd::unique_ptrを使用して2つの表現との完全な例です。 1つがインスタンス化されているかどうか。

+0

これは素晴らしいことです。ちょうど私が欲しいもの。予想以上に簡単!ありがとうございました。 – user3375624

1

ホルトの答えによれば、ここでは可変性が必要です。あなたはまた、表現を格納するためにboost::optional<ReprX>から恩恵を受けるかもしれません。これは、問題の一部である「有効かどうかを知る方法」に役立ちます。

struct A { 

    int get_range() const { 
     if (!_repr2) { 
      _repr2 = Repr2(*_repr1); 
     } 
     return _repr2->get_range(); 
    }  

private: 
    mutable boost::optional<Repr1> _repr1; 
    mutable boost::optional<Repr2> _repr2; 
}; 
+0

私もこれが好きです!私のコードはすでにboostを使用していますので、私はこのようにします。ありがとうございました! – user3375624

+0

boost :: optionalのもう一つの良い点は、クラスのデフォルトのコンストラクタを呼び出さないことです。私はこれを使用しなければなりませんでした。表現のデフォルトのコンストラクタ(私が制御できないライブラリからのもの)は非常に遅く、実際にはランタイムの速度に影響を与えたことが判明しました。 boost :: optionalを使用するように切り替えるだけで、問題は解決しました。ニース! – user3375624