0

在我的系统中,插件程序员可以创建类 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 派生,重新解释它的指针并操纵东西......?)

有人可以给我一个建议吗?第二种方式是否与任何已知模式有关?还是有第三种、更好、更清洁、更强大的方法来解决这个问题?

感谢您的任何建议!

4

1 回答 1

0

从两个选项中选择我会选择“朋友”之一,因为它不需要几行额外的代码,逻辑被压缩(不分成两个单独的类)并且因为它满足您的需求。

然而,可以实现多态解决方案以向插件用户“隐藏”不需要的代码。

所以我的解决方案可能是这两者的混合:

class A_base
{
  friend class GlobalList;

public:
   A_base(int v) : val(v) {}

   int get() { return val; }

private:
   int v;

   void set(int v) { val = v; }
};

class A : public A_base
{
public:
   A(int v) : A_base(v)
   {
      GlobalList::register(this);
   }
};

并且GlobalList必须有一个A *(或类似的)列表。

GlobalList可以直接访问 everyAA_base方法和字段,publicprotectedone private,因为friend class可以访问,所以可以val根据需要进行修改。插件用户必须实例化A类,并且只能访问 and 的部分public,因此保持完整性。AA_base

于 2013-07-14T18:49:30.373 回答