定义:为另一个对象提供一个替身或占位符以控制这个对象的访问。使用代理模式创建代表对象,让代表对象控制某对象的访问,被代理对象可以是远程的对象,创建开销大的对象或需要安全控制的对象。使用代理模式的两个目的:一是保护对象二是增强对象
首先看个类图:
Subject 是顶层接口,RealSubject 是真实对象(被代理对象),Proxy 是代理对象,代理对象持有被代理对象的引用,客户端调用代理对象方法,同时也调用被代理对象的方
法,但是在代理对象前后增加一些处理。在代码中,我们想到代理,就会理解为是代码 增强,其实就是在原本逻辑前后增加一些逻辑,而调用者无感知。代理模式属于结构型
模式,有静态代理和动态代理。
使用JDKProxy创建一个代理。
//每个城镇都需要配对服务
public interface PersonBean{
String getName();
String getGender();
String getInterests();
int getHotOrNotRating();
void setName();
void setGender();
void setInterests();
void setHotOrNotRating();
}
public class PersonBeanImpl implments PersonBean{
String name;
String gender;
String interests;
int rating;
int ratingCount = 0;
//set
//get省略
public int getHotOrNotRating(){
if(ratingCount == 0){
return 0;
}
return rating/ratingCount;
}
public void setHotOrNotRating(int rating){
this.rating = rating;
ratingCount++;
}
//在我们的约会服务中,我们希望顾客可以设置自己的信息,同时又防止他人修改
//HorOrNot 评分则相反,不能自己评价,但是他人可以设置
//这是一种根据访问权限决定客户可否访问对象的代理
}
具体的例子
public class OwnerInvocationHandler implments InvocationHandler{
PersonBean person;
public OwnerInvocationHandler (PersonBean person) {
this.person=person
}
public Object invoke(Object proxy,Meethod method,Object[]args)
throw IllegalAccessException{
if(method.getName().startWith("get")){
return method.invoke(person,args);
}esle if(method.getName().equals("setHotOrNotRating")){
throw new IllegalAccessException();
}else if(method.getName().startWith("set")){
return method.invoke(person,args);
}
return null;
}
PersonBean getOwnerProxy(PersonBean person){
return (PersonBean)proxu.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterface(),
new OwnerInvocationHandler(person)
);
}
}
关键的一点:动态代理之所以叫动态是因为运行时才将代理类创建出来,而不是运行时才将它实例化和handler联系起来的原因。