代理模式 - 适用性和例子

时间:2012-03-12 09:15:26

标签: c++ oop design-patterns proxy-classes

从这里开始:http://www.oodesign.com/proxy-pattern.html

  

适用性&实例

     

代理设计模式适用于需要控制的情况   访问对象,以及何时需要   对对象的复杂引用。常见的情况   代理模式适用于:

     

虚拟代理:延迟昂贵的创建和初始化   对象直到需要,按需创建对象(For   示例仅在doSomething时创建RealSubject对象   方法被调用)。

     

保护代理:代理控制对RealSubject的访问权限   方法,通过在拒绝访问时访问某些对象   其他

     

智能参考:提供对特定对象的复杂访问   例如跟踪对象的引用数和拒绝   如果达到某个数字,则访问,以及加载对象   从数据库到按需存储。

嗯,不能通过为新对象创建单独的函数(构造函数除外)来创建虚拟代理吗?

不能通过简单地将函数设为私有来创建保护代理,并且只允许派生类获得访问权限?或通过朋友班?

智能参考是否可以通过静态成员变量创建,该变量计算创建的对象数量?

在哪种情况下,在访问说明符和继承上首选Proxy方法?

我错过了什么意思?

4 个答案:

答案 0 :(得分:3)

你的问题有点抽象,我不确定我能回答得很好,但这是我对他们每个人的看法。就个人而言,我不同意其中一些事情是这项工作的最佳设计,但这不是你的问题,而是一个意见问题。

虚拟代理 我根本不明白你在这里想说些什么。这里的模式的重点是你可能有一个你知道需要100MB的对象A,并且你不确定你是否需要使用这个对象。

为了避免在需要之前为此对象分配内存,您需要创建一个虚拟对象B,它实现与A相同的接口,如果调用其任何方法,B将创建A的实例,从而避免分配内存,直到它为止需要的。

保护代理 在这里,我认为你误解了模式的使用。我们的想法是能够动态控制对象的访问。例如,您可能希望类A能够访问B类的方法,除非条件C为真。我确信您可以通过使用访问说明符来实现这一点。

智能参与 在这里,我认为你误解了对智能指针的需求。由于这是一个非常复杂的主题,我只会提供一个关于它们的问题的链接:RAII and smart pointers in C++

如果您从未用C语言编写自己管理记忆的语言,那么这可能会解释这种混乱。

我希望这有助于回答你的一些问题。

编辑:

我没有注意到这是标记的c ++所以我认为你确实认识到需要清理动态内存。单个静态引用计数仅在您打算拥有对象的一个​​实例时才有效。如果你创建了一个对象的2000个实例,然后删除它们中的1999个,那么它们中的任何一个都不会释放它们的内存,直到最后一个显示不明显为止(这假设你已经跟踪了所有分配的内存的位置)为了能够释放它!)。

编辑2:

假设您有一个课程如下:

class A {
public:  
  static int refcount;

  int* allocated_memory;

  A() { 
    ++refcount;
    allocated_memory = new int[100000000];
  }

  ~A() { 
    if(! --refcount) {
      delete [] allocated_memory;
    }
  }
}

使用它的一些代码:

int main() {
  A problem_child;  // After this line refcount == 1
  while(true) {
    A in_scope;     // Here refcount == 2

  }                 // We leave scope and refcount == 1. 
                    // NOTE: in_scope.allocated_memory is not deleted
                    //       and we now have no pointer to it. Leak!
  return;
} 

正如您在代码中所看到的,refcount计算对所有对象的所有引用,这会导致内存泄漏。如果你需要,我可以进一步解释,但这本身就是一个单独的问题。

答案 1 :(得分:1)

我不是专家,但这是我对虚拟代理的想法:如果我们通过单独的函数控制初始化,请说bool Create();那么初始化的责任和控制权在于客户端班上的。使用虚拟代理,目标是在类中保留创建控制,而无需客户端知道。

保护代理:受保护的主题可能包含不同类型的客户端,需要对所有主题方法进行无保护/不受限制的访问以及应该允许访问方法子集的其他人因此需要保护代理。

答案 2 :(得分:0)

代理是一个对象,表现为添加某些控件/行为的不同对象。智能指针就是一个很好的例子:它访问对象就像使用原始指针一样,但它也控制着该对象的生命周期。

答案 3 :(得分:0)

很好地质疑是否有替代问题的标准解决方案。设计模式代表了适用于许多人的解决方案,其优势在于,有经验的程序员很有可能会识别模式,从而更容易维护代码。但是,所有设计都代表权衡,模式有成本。因此,您挑战模式的使用并考虑替代方案是正确的。

在许多情况下,设计不只是使代码工作,而是考虑它的结构。哪一段代码“知道”什么。您建议使用Virtual Prozy移动的替代方法(如fizzbuzz所说)从代理到客户端的创建知识 - 客户端必须“知道”调用Create(),因此知道类的​​生命周期。然而,对于代理,他只是创建一个他视为工人的对象,然后当代理决定它是有意义的时,就会发生无形的创造。将责任重构到代理中是有价值的,它允许我们在将来改变那些生命周期规则而不改变任何客户。

保护代理:您的提案要求客户端具有继承关系,以便它们可以使用受保护的方法。一般来说,夫妻客户和工人太紧,所以我们引入代理。

智能参考:不,单个静态计数不好。您需要计算对单个实例的引用。

如果您仔细研究每个案例,您会发现设计模式有其优点。如果你试图实现一个替代方案,你可以从一些简单的设计模式开始,然后发现当你开始重构和改进代码,删除deuplication等等你最终重新发明设计模式 - 这是一个非常好的结果