代理模式
2018-01-20 本文已影响8人
yangzai
- 定义:
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 -
UML:
image.png - 模型:
明星->经纪人
//抽象出明星与经纪人行为
public interface Star {
void confer();//面谈
void signContract();//签合同
void bookTicket();//订票
void sing();//唱歌
void collectMoney();//收尾款
}
//明星
public class RealStar implements Star{
@Override
public void confer() {
System.out.println("RealStar.confer()");
}
@Override
public void signContract() {
System.out.println("RealStar.signContract()");
}
@Override
public void bookTicket() {
System.out.println("RealStar.bookTicket()");
}
@Override
public void sing() {
System.out.println("张学友.sing()");//真实角色的操作:真正的业务逻辑
}
@Override
public void collectMoney() {
System.out.println("RealStar.collectMoney()");
}
}
//经纪人:
public class ProxyStar implements Star{
private Star star;//真实对象的引用(明星)
@Override
public void confer() {
System.out.println("ProxyStar.confer()");
}
@Override
public void signContract() {
System.out.println("ProxyStar.signContract()");
}
@Override
public void bookTicket() {
System.out.println("ProxyStar.bookTicket()");
}
@Override
public void sing() {
star.sing();//真实对象的操作(明星唱歌)
}
@Override
public void collectMoney() {
System.out.println("ProxyStar.collectMoney()");
}
public ProxyStar(Star star) {//通过构造器给真实角色赋值
this.star = star;
}
}
//测试
public static void main(String[] args) {
Star real = new RealStar();
Star proxy = new ProxyStar(real);
proxy.confer();
proxy.signContract();
proxy.bookTicket();
proxy.sing();//真实对象的操作(明星唱歌)
proxy.collectMoney();
}
通过代理对象,明星与经纪人的职责清晰, 明星只需关注自身逻辑实现,非业务逻辑部分,后期通过经纪人完成即可。例如跟各个公司洽谈合作事宜由代理人完成即可。
- 以上代理是静态代理,对于 静态语言,java、c、c++等,他们都需要编译再执行。静态代理是由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。 - java 中的动态代理实现需要以下几步:
- 1.定义代理对象的行为
- 2.实现InvocationHandler接口
- 3.使用Proxy.newProxyInstance创建代理对象
- 4.调用代理对象方法。
//定义代理对象的行为
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;
@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 {
if(method.getName().startsWith("get")){
//调用被代理对象行为
return method.invoke(person,args);
}else if(method.getName().equals("setHotOrNotRating")){
return new IllegalAccessException();
}else if(method.getName().startsWith("set")){
return method.invoke(person,args);
}
return null;
}
}
//使用
public class MatchService {
public MatchService() {
PersonBean joe = getPersonInfo("joe", "male", "running");
PersonBean OwnerProxy = getOwnerProxy(joe);
System.out.println("Name is " + OwnerProxy.getName());
System.out.println("Interests is " + OwnerProxy.getInterests());
OwnerProxy.setInterests("Bowling");
System.out.println("Interests are " + OwnerProxy.getInterests());
OwnerProxy.setHotOrNotRating(50);
System.out.println("Rating is " + OwnerProxy.getHotOrNotRating());
OwnerProxy.setHotOrNotRating(40);
System.out.println("Rating is " + OwnerProxy.getHotOrNotRating());
System.out.println("**************");
}
PersonBean getPersonInfo(String name, String gender, String interests) {
PersonBean person = new PersonBeanImpl();
person.setName(name);
person.setGender(gender);
person.setInterests(interests);
return person;
}
PersonBean getOwnerProxy(PersonBean person){
return (PersonBean) Proxy.newProxyInstance(person.getClass()
.getClassLoader(), person.getClass().getInterfaces(),
new OwnerInvocationHandler(person));
}
//测试
public static void main(String[] args) {
MatchService mMatchService=new MatchService();
}
}
通过上述代码,我们不需要手动创建代理类,java在运行时根据我们传入的行为组接口,帮我们动态创建了一个proxy,在调用行为组方法是,proxy会调用InvocationHandler的invoke方法,在这个方法里我们可以调用真实对象的方法,或者添加一些其他逻辑,比如方法前、后打印时间。