私のシステムでは、プラグイン プログラマーが、データ ストレージとして使用されるクラス A の複数のインスタンスを作成できます。
class A
{
protected:
int val;
public:
A( int v ) : val(v)
{
GlobalList::register(this);
}
int get() { return val; }
};
私は今、そのようなオブジェクトにいくつかの「ビュー」を持つ必要があります。つまり、A へのアクセサ関数を持つ必要があるさまざまなモジュールがあり、他のモジュールには表示されません。1 つのケースとして、オブジェクトを作成するプラグイン プログラマーはゲッターのみを参照する必要があります。ただし、A レジスター自体がグローバルな静的リスト クラスであり、時々アクセスしてその値を変更するメカニズムを使用します。
私の質問は、これを適切に設計する方法です。通常、これを解決するには、A をいくつかの抽象インターフェイスから派生させて実装し、各モジュールに A へのカスタムの制限されたインターフェイス ポインターのみを与えます。ただし、プラグイン プログラマーがオブジェクトをインスタンス化してアクセスできるため、これはできません。とにかくすべてのパブリック関数に。
次の 2 つのオプションが考えられます。
1) プライベートな change() メソッドを A に追加し、GlobalList に A* のリストを与え、GlobalList を A のフレンドにします。その後、GlobalList は A::change を呼び出すことができますが、ユーザーは呼び出すことができません。ただし、A にカスタムの「ビュー」を持つクラスを追加するたびに、フレンド リストを拡張する必要があります。これは、A のクラス定義を常に変更する必要があるため、最適な設計とは言えません。
2) A の「ビュー」ごとに、A から派生し、change() メソッドを持つある種のアクセサ クラスを作成します。次に、GlobalList に Accessor* のリストを指定します。A のインスタンスを GlobalList クラスに登録するときは、次のように、インスタンスへのポインターをアクセサー関数のポインターにキャストします。
class A
{
protected:
int val;
public:
A( int v ) { val = v; }
int get() { return val; }
};
class AccessorA : public A
{
public:
void change( int v ) { val = v; }
};
GlobalList::register( A* obj )
{
mlist.push_back( (AccessorA*) obj );
}
次に、GlobalList は、A の変更機能を提供するポインターのリストを反復処理できます。A を作成したユーザーは、(アクセスできないプライベートであっても) change() メソッドを見ることはなく、A のクラス定義は、 A のビューを持つ GlobalList のような新しいクラスを追加しても、変更されました。
2 番目の方法はうまくいき、なんとなくきれいに見えますが、私には奇妙に見えます。この設計が劇的に失敗する致命的なケースを見逃しているという悪い予感がします。(特に: そんなに簡単なら、誰もが A から派生し、そのポインタを再解釈して、操作できる... ?)
誰かが私にアドバイスをくれますか?2 番目の方法は、既知のパターンに関連していますか? または、これを解決するための、より優れた、よりクリーンで、より堅牢な方法がありますか?
ご提案ありがとうございます。