2

当然,我正在阅读有关DoFactoryWikipedia以及 Stack Overflow 上的代理。一切都很清楚,除了Real Subject。在 DoFactory 上,Proxy 定义为:

为另一个对象提供代理或占位符以控制对其的访问。(添加了粗体字)

如果它的目的是控制访问Real Subject,为什么Real Subject不隐瞒Client呢?

这是代理的UML图:

代理 UML

在代码示例中,Real Subject定义为:

class RealSubject : Subject
{
    ...
}

客户端通过它创建一个实例Proxy并“控制访问” Real Subject

Proxy proxy = new Proxy();
proxy.Request();

但是(从我看到的几个例子中)没有什么可以阻止 Client 实例化Real Subject和访问它的方法。我想知道这是为什么?

4

2 回答 2

1

我会给你一个例子,我想它会帮助你了解代理的目的/能力,并尝试展示控制对对象的访问的含义。

假设我有一个DataStore实现给定接口的对象(或实体)存储IModel

我的合同如下:

public interface IDataStore(){

   // Return a given model by its id
   public IModel getModelById(Long ID);

   // Return the set of models that were modified by DataStore Clients.
   public Collection<IModel> getModifiedModels();
}

第二种方法合同有点复杂,解决起来很麻烦。一个(复杂的)解决方案是保留每个IModel返回的副本,然后在原始元素之间进行比较。使用代理模式,我们的 DataStore 可以以优雅的方式履行他的合同:当查询具有给定 id 的模型时,他实际上会向您返回一个代理,该代理会将任何修改通知回数据存储。

出于说明目的,以下是合同解决方案的外观:

// The following is equivalent to "Subject" using your nomenclature
public interface IModel{

   public Long getId()
   public void setId(Long id);
}

// The following is equivalent to the "RealSubject"
public class RealModel implements IModel{

   Long id;
   public void getId(){
      return id;
   }
   public void setId(Long newid){
      this.id = newid;
   }
}

最后是我们的代理:

public class ModelProxy extends RealModel implements IModel{

   IModel proxiedModel;
   DataStore datastore;//our datastore

   public ModelProxy(IModel model, DataStore ds){
       proxiedModel=model;
       datastore = ds;
   }

   public void setId(Long newid){

      datastore.addModified(this);
      //  (Assume the DataStore implementation has the addModified method)
      //  The more important here is that we are really "controlling access" to 
      //  our model : before allowing client to modify the id, we're
      //  notifying the store of the modification, and the client hasn't to know about 
      //  that as he's only aware of the IModel interface contract.
      this.id = newid;


   }

}
于 2013-11-29T14:42:00.493 回答
1

您当然可以实现代理模式,以便 RealSubject 对客户端不可见。事实上,如果每个客户端都只使用代理,那将是一个很好的 OO 方法。

另一方面,代理通常用于提高效率或安全性,或添加延迟加载等功能。如果有很多客户端,其中一些可能不需要代理添加的内容,会直接使用 RealSubject。

在库 API 的情况下,RealSubject 可能被公开(公开)以允许任何客户端实现其自己的代理。然后 RealSubject 对客户端可见,即使客户端只使用它的代理。

另一种情况是 Proxy 可能只提供 RealSubject 的部分接口。以控制对 RealSubject 的访问的保护代理为例。客户端通过身份验证后,可能会被允许直接访问RealSubject,并且代理可以被销毁。

如您所见,代理的价值通常取决于所涉及的客户端。一些客户端可能专门使用它,在这种情况下可以隐藏 RealSubject。其他客户端可能会暂时使用它,而其他客户端可能根本不使用它。

于 2013-11-28T22:32:26.313 回答