2016-03-20 7 views
0

私は、データベース行へのアクセスを提供するクラスを含むライブラリを設計しています。基礎となるデータは、valueがunion型のマップに保持されます。以下の基本クラスを考えてみましょう:個々のプロパティ/アクセサの集計に基づいてクラス階層を設計する

class dbObject 
{ 
    protected: 
    // Get and set property values using generic name for property 
    union_type GetPropertyValue(string property_name); 
    void SetPropertyValue(string property_name, union_type value); 

    // Add mapping from generic property name to column name 
    void AddPropertyMapping(string property_name, string column_name); 

    private: 
    map<property_name, column_name> 
    map<column_name, union_type> 
}; 

DBOBJECTから継承する各クラスが

  • に必要とされることが
  • にアクセスする必要がある列のためのプロパティマッピングを追加し、そのプロパティ
  • ためのアクセサを提供

ライブラリユーザーに提示される最終的なインターフェイスクラスには、適切なアクセサがあり、基になる構造/実装が隠されるようにします。ここでの動機付けは、ほとんどのクラスが同じデータの大部分を共有しているため、クラスごとに個別に記述するのではなく、アクセサとマッピング設定コードを継承する必要があるということです。もともと私は、共有アクセサのいくつかのセットを含む各派生クラスを構造化された例:あなたが見ることができるように

class dbDerivedObjectOne : dbObject 
{ 
    public: 
    int GetPropertyOne(); 
    void SetPropertyOne(int value); 
    string GetPropertyTwo(); 
    void SetPropertyTwo(string value); 
}; 

class dbDerivedObjectTwo : dbDerivedObjectOne 
{ 
    public: 
    double GetPropertyThree(); 
    void SetPropertyThree(double value); 
    int GetPropertyFour(); 
    void SetPropertyFour(int value); 
}; 

// This is the API class which is presented to the library user 
// It has inherited all the necessary accessors and setup code 
class dbInterfaceClass : dbDerivedObjectTwo 
{ 
}; 

、この階層は、このように葉/インターフェース・クラスのニーズをアクセサものに基づいてではなく、本当のさ「であります適切な設計で見えると期待される「-a」の関係です。また、一部のクラスが親クラスに既に公開されているプロパティの一部のサブセットにアクセスする必要があるが、親クラスのすべてのプロパティを公開したくないという問題が発生しました。その一部は派生クラスに対して無意味/存在しないからです。

リファレンスパターンは知られていませんが、現在は派生したクラスを単一のプロパティクラスに分割し、複数の継承を使用してインターフェイスクラスを作成するリファクタに向かっています。

class dbObjectProperty 
{ 
    union_type GetProperty(string property_name) 
    void SetProperty(string property_name, union_type value) 
}; 

class dbPropertyOne : dbObjectProperty 
{ 
    // calls dbObjectProperty::GetProperty() with its property name 
    // returns the int from the union_type 
    int GetPropertyOne(); 

    // wraps the int in a union_type 
    // calls dbObjectProperty::SetProperty() with its property name 
    int SetPropertyOne(int value); 
}; 

class dbPropertyTwo : dbObjectProperty 
{ 
    // calls dbObjectProperty::GetProperty() with its property name 
    // returns the string from the union_type 
    string GetPropertyTwo(); 

    // wraps the string in a union_type 
    // calls dbObjectProperty::SetProperty() with its property name 
    void SetPropertyTwo(string value); 
}; 

class InterfaceClassOne : dbPropertyOne, dbPropertyTwo 
{ 
    // exposes all of the accessors from its parent classes 
} 

この溶液をはるか粒状であり、私は、それぞれ独自のアクセサ/ミューテータを提供する(潜在的に共有される)プロパティのセットとして各インターフェースクラスを構築することを可能にします。しかし、実際の実装には、25-30の異なるプロパティクラスを継承するクラスが含まれます。これは恐ろしい多重継承設計のようです。また、これは継承コンセプトのかなりの乱用のようです。インタフェースクラスは実際にはdbObjectPropertyとの "関係"には合いませんが、実際にはコレクションであり、複数の継承を悪用してアクセッサコードの重複を避けることができます。

質問:

  1. 私が見てする必要があり、この種の構造のための確立されたデザインパターンがありますか?
  2. アクセサーコードの重複を避けながらこの問題を解決する別の方法がありますか?
  3. 私が貧弱な/危険な設計を検討している多重継承ソリューションか、それほど厳格ではない言語で簡単になるようなシステムを悪用させるC++の性質ですか?

答えて

1

だから私はあなた自身がいくつかのタイピング作業を省くことを理解しているからです。私はマクロを提案しますが、私はそれらの専門家ではありません;)ので、彼らは働くことができるかどうかわかりません(しかし、調べる価値があるかもしれません)。

私は別の解決策が、ここで簡単な例(VC++)です見つけた:

template<typename T> 
class Property { 
private: 
    std::map<std::string, union_type>& map_ref; 
    const std::string name; 
public: 
    Property(std::map<std::string, union_type>& my_map, std::string&& name) : map_ref(my_map), name(name) {} 

    T Get() const { 
     return static_cast<T>(map_ref[name]); 
    } 

    void Set(T new_value) const { 
     map_ref[name] = static_cast<union_type>(new_value); 
    } 
}; 

class MyObject { 
private: 
    std::map<std::string, union_type> my_map; 
public: 
    const Property<int> my_int{ my_map, "my_int" }; 
}; 

私は、あなたが他の人にあなたのunion_typeから行く、具体的方法を知らないので、私は、静的なキャストwhithここでそれを表現。

これの欠点は、取得と設定にもう少し時間がかかることです。 my_object.my_int.Get()。それでも、ゲッターやセッターをすべて入力する必要がなく、作業を省くことができます。

これの利点は、(どちらが、私見、...いいです)あなたはまだ代わりになどだけPropertyOne、PropertyTwo、の、実際のプロパティ名を使用してアクセスを持っているということです

+0

明確にするために、Iいくつかの入力作業を省くだけでなく、新しいプロパティを変更したり追加したりする必要があるときに、多くのメンテナンスや拡張の頭痛を避けようとしています。 "Diameter"プロパティのアクセサー関数を変更しなければならないのは、25種類のクラスに重複している場合の悪夢です。これは考えられている解決策であり、私はテンプレートクラスを使用することを考えていませんでした(しかし、それは明らかな選択肢のようです)。提案していただきありがとうございます。答えとしてマークする前に、これ以上の回答があるかどうか少し確認します。 – NAW

+0

私が十分な解決策を提示しなかった場合は、自分の回答を投稿することもできます。それは後でこの質問を見つける人々を助けるかもしれません。 –

関連する問題