我正在阅读DoFactory和Wikipedia上的代理,以及Stack Overflow。
一切都很清楚,Real Subject
除外。在DoFactory上,Proxy定义为:
为另一个对象提供代理或占位符以控制对其的访问。 (加粗字体)
如果其目的是控制对Real Subject
的访问权限,为什么Real Subject
未隐藏Client
?
这是代理的UML图:
在代码示例中,Real Subject
定义为:
class RealSubject : Subject
{
...
}
客户通过它创建Proxy
的实例并“控制对Real Subject
的访问权”:
Proxy proxy = new Proxy();
proxy.Request();
但是(从我看到的几个例子中)没有什么可以阻止客户端实例化Real Subject
并访问其方法。我想知道为什么会这样?
答案 0 :(得分:1)
您当然可以实现代理模式,以便RealSubject对客户端不可见。实际上,如果每个客户都希望只使用代理,那将是一个很好的OO方法。
另一方面,代理通常用于提高效率或安全性,或添加延迟加载等功能。如果有许多客户端,其中一些可能不需要代理添加的客户端,并将直接使用RealSubject。
对于库API,可能会暴露(公共)RealSubject以允许任何客户端实现自己的代理。然后,即使客户端仅使用其代理,RealSubject也会对客户端可见。
另一种情况是Proxy可能只提供RealSubject的部分接口。以控制对RealSubject访问的保护代理为例。对客户端进行身份验证后,可以允许直接访问RealSubject,并且可以处理代理。
如您所见,代理的价值通常取决于所涉及的客户。有些客户可能只使用它,在这种情况下可以隐藏RealSubject。其他客户可能暂时使用它,而其他客户可能根本不使用它。
答案 1 :(得分: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;
}
}