在我的系统中,插件程序员可以创建类 A 的多个实例,用作数据存储。
class A
{
protected:
int val;
public:
A( int v ) : val(v)
{
GlobalList::register(this);
}
int get() { return val; }
};
我现在需要对这样的对象有几个“视图”,即有不同的模块应该对 A 具有访问器功能,而其他模块不应该看到。一种情况是,创建对象的插件程序员应该只看到 getter。但是,我使用一种机制,其中 A 注册自己是一个全局静态列表类,它会不时访问它并更改它的值。
我的问题是,如何正确设计它。通常,我会通过让 A 从多个抽象接口派生并实现几个抽象接口来解决这个问题,并且只为每个模块提供其指向 A 的自定义受限接口指针。但是,我不能这样做,因为插件程序员实例化了对象,因此可以访问无论如何,所有公共职能。
我可以想到两个选择:
1)给A添加一个私有的change()方法,给GlobalList一个A*的列表,让GlobalList成为A的朋友。GlobalList然后可以调用A::change,但是用户不能。但是,对于每个在 A 上具有自定义“视图”的附加类,我必须扩展朋友列表,这不是最好的设计,因为我经常需要更改 A 的类定义。
2) 对于 A 上的每个“视图”,创建某种访问器类,从 A 派生,并具有 change() 方法。然后给 GlobalList 一个 Accessor* 的列表。在 GlobalList 类中注册 A 的实例时,将指向该实例的指针强制转换为 Accessor 函数的指针,如下所示:
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 这样的新类。
第二种方法有效,它看起来更干净,但对我来说看起来很奇怪。我有一种不好的感觉,我错过了一些致命的案例,这个设计严重失败。(特别是:如果这么简单,每个人都可以从 A 派生,重新解释它的指针并操纵东西......?)
有人可以给我一个建议吗?第二种方式是否与任何已知模式有关?还是有第三种、更好、更清洁、更强大的方法来解决这个问题?
感谢您的任何建议!