代理模式的定义为:为其他对象提供一个代理来控制对它的访问。

英文定义:Provide a surrogate or placeholder for another object to control access to it.

这个中文定义没有很好的反映出原本的意思。英文定义中的surrogate与placeholder都有代理的意思。但是他们之间肯定存在微妙的差别。

以下翻译结果,来自​​有道​

surrogate

  • n. 代理;代用品;遗嘱检验法官
  • vt. 代理;指定某人为自己的代理人
  • adj. 代理的;替代的

placeholder


n. 占位符



我的理解是,surrogate是代理中动的一方面,而placeholder则是静的一面。



代理模式有很多分类:


Remote Proxy


    A remote proxy provides a local representative for an object in a difference address space.


    Remote proxies are responsible for encoding a request and its arguments and for sending the encoded request to the real subject in a difference address space.



Virtual Proxy


    A virtual proxy creates expensive objects on demand.


    Virtual proxies may cache additional information about the real subject so that they can postpone accessing it.



Protection Proxy


    A protection proxy controls access to the original object.


    Protection proxies check that the caller has the access permissions required to perform a request.



Smart Reference


    A smart reference is a replacement for a bare pointer that performs additional actions when an object is accessed.



除了以上比较重要的用途外,还有以下类型:



Firewall Proxy


Caching Proxy


Synchronization Proxy


Complexity Hidding Proxy


Copy-On-Write Proxy



可见Proxy的用途是非常广泛的。



Proxy可以与real subject继承自同一基类,这样任何用到proxy的地方,都可已用real subject来代替,


这一点与decorator模式非常相似,但是他们的intent是不同的。



以下例子是利用java提供的Proxy实现的Protection Proxy。



定义subject对应接口


public interface PersonBean {
String getName();
String getGender();
String getInterests();
int getHotOrNotRating();

void setName(String name);
void setGender(String gender);
void setInterests(String interests);
void setHotOrNotRating(int rating);
}




public class PersonBeanImpl implements PersonBean {
String name;
String gender;
String interests;
int rating;
int ratingCount = 0;

public String getName() {
return name;
}

public String getGender() {
return gender;
}

public String getInterests() {
return interests;
}

public int getHotOrNotRating() {
if (ratingCount == 0) return 0;
return (rating / ratingCount);
}

public void setName(String name) {
this.name = name;
}

public void setGender(String gender) {
this.gender = gender;
}

public void setInterests(String interests) {
this.interests = interests;
}

public void setHotOrNotRating(int rating) {
this.rating += rating;
ratingCount++;
}
}



定义proxy的handler


import java.lang.reflect.*;

public class OwnerInvocationHandler implements InvocationHandler {
PersonBean person;

public OwnerInvocationHandler(PersonBean person) {
this.person = person;
}

public Object invoke(Object proxy, Method method, Object[] args)
throws IllegalAccessException {
try {
if (method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if (method.getName().equals("setHotOrNotRating")) {
throw new IllegalAccessException();
} else if (method.getName().startsWith("set")) {
return method.invoke(person, args);
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}


import java.lang.reflect.*;

public class NonOwnerInvocationHandler implements InvocationHandler {
PersonBean person;

public NonOwnerInvocationHandler(PersonBean person) {
this.person = person;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
try {
if (method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if (method.getName().equals("setHotOrNotRating")) {
return method.invoke(person, args);
} else if (method.getName().startsWith("set")) {
throw new IllegalAccessException();
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}


测试代码


import java.lang.reflect.*;
import java.util.ArrayList;

public class MatchMakingTestDrive {
// instance variables here
ArrayList<PersonBean> persons;

public static void main(String[] args) {
MatchMakingTestDrive test = new MatchMakingTestDrive();
test.drive();
}

public MatchMakingTestDrive() {
initializeDatabase();
}

public void drive() {
PersonBean joe = getPersonFromDatabase("Joe Javabean");
PersonBean ownerProxy = getOwnerProxy(joe);
System.out.println("Name is " + ownerProxy.getName());
ownerProxy.setInterests("bowling, Go");
System.out.println("Interests set from owner proxy");
try {
ownerProxy.setHotOrNotRating(10);
} catch (Exception e) {
System.out.println("Can't set rating from owner proxy");
}
System.out.println("Rating is " + ownerProxy.getHotOrNotRating());

PersonBean nonOwnerProxy = getNonOwnerProxy(joe);
System.out.println("Name is " + nonOwnerProxy.getName());
try {
nonOwnerProxy.setInterests("bowling, Go");
} catch (Exception e) {
System.out.println("Can't set interests from non owner proxy");
}
nonOwnerProxy.setHotOrNotRating(3);
System.out.println("Rating set from non owner proxy");
System.out.println("Rating is " + nonOwnerProxy.getHotOrNotRating());
}

PersonBean getOwnerProxy(PersonBean person) {
return (PersonBean)Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new OwnerInvocationHandler(person));
}

PersonBean getNonOwnerProxy(PersonBean person) {
return (PersonBean)Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new NonOwnerInvocationHandler(person));
}

private void initializeDatabase() {
persons = new ArrayList<PersonBean>();
PersonBean personBean = new PersonBeanImpl();
personBean.setName("Joe Javabean");
personBean.setGender("male");
personBean.setInterests("Drinking");
personBean.setHotOrNotRating(2);
persons.add(personBean);
}

private PersonBean getPersonFromDatabase(String name) {
for (PersonBean person : persons) {
if (person.getName().equals(name)) {
return person;
}
}
return null;
}
}





【设计模式】之代理模式(Proxy)_设计模式