设计模式 - 代理模式
目录
- 代理模式的定义
- 代理模式的类图
- Java 动态代理的类图
- 对象村的配对(动态代理)
代理模式的定义
代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。
代理模式的类图
首先是 Subject,它为 RealSubject 和 Proxy 提供了接口。通过实现同一接口,Proxy 在 RealSubject 出现的地方取代它。
RealSubject 是真正做事的对象,它是被 proxy 代理和控制访问的对象。
Proxy 持有 RealSubject 的引用。在某些例子中,Proxy 还会负责 RealSubject 对象的创建与销毁。客户和 RealSubject 的交互都必须通过 Proxy。因为 Proxy 和 RealSubject 实现相同的接口,所以任何用到 RealSubject 的地方,都可以用 Proxy 取代。Proxy 也控制了对 RealSubject 的访问。
Java 动态代理的类图
对象村的配对(动态代理)
实现对象村的约会服务系统,在服务中加入"Hot" 和 “Not” 的评鉴。
系统不应该允许用户篡改别人的兴趣,也不应该允许让用户给自己打分数。
-
步骤一:创建两个 InvocationHandler
InvocationHandler 实现了代理的行为,Java 负责创建真实代理类和对象,我们只需提供在方法调用发生时知道做什么的 handler。
-
步骤二:写代码创建动态代理
我们需要写一些代码产生代理类,并实例化它。
-
步骤三:利用适当的代理包装任何 PersonBean 对象。
JavaBean
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 PersonBeanImpl() {
}
public PersonBeanImpl(String name, String gender, String interests) {
this.name = name;
this.gender = gender;
this.interests = interests;
}
@Override
public String getName() {
return name;
}
@Override
public String getGender() {
return gender;
}
@Override
public String getInterests() {
return interests;
}
@Override
public int getHotOrNotRating() {
if (ratingCount == 0 ) return 0;
return rating / ratingCount;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public void setGender(String gender) {
this.gender = gender;
}
@Override
public void setInterests(String interests) {
this.interests = interests;
}
@Override
public void setHotOrNotRating(int rating) {
this.rating += rating;
ratingCount++;
}
}
InvocationHandler
public class OwnerInvocationHandler implements InvocationHandler {
PersonBean person;
public OwnerInvocationHandler(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")) {
throw new IllegalAccessException();
} else if (method.getName().startsWith("set")) {
return method.invoke(person, args);
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
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;
}
}
测试类
public class MatchMakingTestDrive {
public static void main(String[] args) {
MatchMakingTestDrive test = new MatchMakingTestDrive();
test.drive();
}
public void drive() {
PersonBean joe = new PersonBeanImpl("joe", "male", null);
PersonBean ownerProxy = getOwnerProxy(joe);
System.out.println("name is " + ownerProxy.getName());
ownerProxy.setInterests("bowling, Go");
try {
ownerProxy.setHotOrNotRating(10);
} catch (Exception e) {
e.printStackTrace();
}
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) {
e.printStackTrace();
}
nonOwnerProxy.setHotOrNotRating(3);
System.out.println("Rating is " + nonOwnerProxy.getHotOrNotRating());
}
public PersonBean getOwnerProxy(PersonBean person) {
return (PersonBean) Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new OwnerInvocationHandler(person)
);
}
public PersonBean getNonOwnerProxy(PersonBean person) {
return (PersonBean) Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new NonOwnerInvocationHandler(person)
);
}
}