4

私はこのトピックの調査に 1 日を費やしました。そのため、このトピックに関するいくつかの知識が散在している状態で、この質問をお送りしました。私が達成しようとしていることを説明させてください。差し迫った質問に対する解決策、または問題に完全に取り組む別の方法を提案できるかもしれません.

XAMLファイルがWPFでどのように機能するかに関連する何かを模倣しようとしています。ここでは、本質的に XML 定義からオブジェクト ツリーをインスタンス化しています。これが正しくない場合は、お知らせください。それ以外の場合、この問題はWPFC#、または管理されているものとは関係ありません-同様の概念であるため、私はそれについてのみ言及します..

そのため、XMLパーサー クラスは既に作成しており、 ObjectNodeオブジェクトに基づいてノード ツリーを生成しています。ObjectNodeオブジェクトはtypeと呼ばれる文字列値を保持し、子ObjectNodeオブジェクトのstd::vectorを持ちます。

次のステップは、 ObjectNodeツリーのデータに基づいてオブジェクトのツリーをインスタンス化することです。同じObjectNodeツリーが複数回インスタンス化されるか、必要に応じて遅延される可能性があるため、この中間ObjectNodeツリーが必要です。作成されるオブジェクトのツリーは、ツリー内のノードが共通の基本クラスの子孫になるようなものです。これは、今のところMyBaseとして参照できます。リーフ ノードは任意の型にすることができ、必ずしもMyBaseから派生させる必要はありません。

これをさらに困難にするために、ツリーに含まれる可能性のあるオブジェクトのタイプがわからないため、新しいタイプをファクトリに登録できるようにする必要があります。

ブーストの工場を認識しています。彼らのドキュメントには、このページに興味深い小さなデザイン パラグラフがあります。

o コンストラクターに転送されるいくつかの引数を取るファクトリが必要な場合があります
。 o おそらくスマート ポインターを使用したい
場合があります。 o さまざまな種類のオブジェクトを作成するためにいくつかのメンバー関数が必要な場合があります。
o ポリモーフィック ベースが必ずしも必要ではない場合があります。 o 後でわかるように、ファクトリ基本クラス
はまったく必要ありません 。o
スタック上にオブジェクトを作成するために #new# を使用せずに、単にコンストラクターを呼び出したい場合があります。
カスタマイズされたメモリ管理を使用します。

私はこれをすべて正しく理解していないかもしれませんが、私がやろうとしていることはブーストの工場で達成できると述べているようです. しかし、私が見つけたすべての例は、すべてのオブジェクトが基本型から派生したファクトリを説明しているようです。

これに関するガイダンスは大歓迎です。

御時間ありがとうございます!

4

4 に答える 4

2

次のようなファクトリ メソッドの typedef を定義します。

typedef void* (*FactoryMethod)(const vector<string>& parameters);

つまり、すべてのファクトリ メソッドは、何かへのポインター (void へのポインター) を返し、文字列の const ベクトルをパラメーターとして受け取ります。

登録データは次のようになります。

std::map<string, FactoryMethod> globalFactoryMethods;

... ここで、キーは型stringで、値は対応するファクトリ メソッドへのポインターです。新しいファクトリ メソッドを持つ新しい型がある場合は、それを (実行時に) マップに追加して「登録」します。

登録されたファクトリ メソッドを使用した構築は、次のようになります (疑似コード)。

foreach (Node node in nodes)
{
  string type = node.type;
  FactoryMethod factoryMethod = globalFactoryMethods[type];
  void* constructedLeaf = (*factoryMethod)(node.nParameters, node.pParameters);
  //do something here with constructed leaf
}

リーフ ノードは任意の型にすることができ、必ずしも MyBase から派生させる必要はありません。

これは C++ の問題です。それらが何であるかわからない場合、どのようにそれらを削除しますか?

C# (C++ とは異なり) は、それらが何であるかを知らなくても削除できます。むしろ、削除する必要はありません。これはマネージド メモリであり、すべてが のサブクラスであるためSystem.Objectです。

于 2010-05-23T23:57:17.403 に答える
1

あなたがあなたの問題を説明してくれたのはとても良いことです:)

もちろん、あらゆる種類の型を作成できるファクトリを持つというアイデアは非常に魅力的ですが、複雑で不必要でもあります。void*残念ながら見た目ほど魅力的ではないの魅力は理解しています。そのような獣に対してできる唯一のことは、それを適切なポインターにキャストすることです...これには、コンパイル時に型が何であるかを知る必要があります!

がありstd::vector<void*>、このベクトルの内容を出力するように頼んだとします。どうしますか?

ファクトリで簡単に処理できるようにするために設計した基本クラスから、作成したクラスを継承するように人々に強制することはまったく問題ありません。

struct Object: boost::noncopyable
{
  virtual Object* clone() const = 0;
  virtual ~Object() {}
};

これは、このクラスからの継承を要求するよりも、実際には非常に小さな制約です。clone代わりに、仮想デストラクタを取得し、オブジェクトのスライスの問題を回避するために、(メンバー関数のおかげで) クラスをポリモーフィックにコピーできるようにします。

いくつかのデザインパターンを読むべきだと思います:

  • プロトタイプは Factory を実装するために広く使用されていますが、それが唯一の方法ではありません
  • Factory、あなたはすでに知っているようです、おそらくそれAbstractFactoryもあなたを助けるでしょう
  • コンポジットは、オブジェクトのツリーを処理するために必須です
  • Visitor前方互換性のある操作方法を定義するのに本当に役立ちますComposite
于 2010-05-24T11:30:40.317 に答える
0

おそらく次のようなことを正しく理解したと思うなら:

void register(string constructor, void*(*method)(...)); // put in map

template<class T>
T* new_(string subclass, ...) {
  return static_cast<T*>(constructors_[subclass](...));
}
于 2010-05-24T00:11:17.750 に答える
0

私はあなたの質問を本当に理解することはできませんが、トピックから、あなたは任意の登録オブジェクトを作成しようとしていると思います.おそらくデザインパターン「プロトタイプ」を見ることができます
オールマイティwikiはこちら

于 2010-05-24T01:09:00.880 に答える