有的时候类 A A 可能无法访问类,但是有一个类 C C ,它可以访问且 B B 也能访问到,那么 A A 就可以通过间接的访问到 A A 。
在Java**代理模式**中中三类角色:
- 抽象角色,定义一系列的行为方法,可以用接口或者抽象方法表示。
- 真实角色,它才真正做事的角色。
- 代理角色,代理角色持有真实角色的一个引用,当访问代理角色时,它可以帮助我们间接的访问到真实角色(情况时,我们无法直接访问真实角色)。代理对象提供与真实角色对象相同的接口,以便完全代替真实角色。当我们操纵代理对象的行为时,它则会进而操纵其引用真实对象相应的行为。代理对象可以在操纵真实对象的行为时附加自己的行为动作。
下面以一个到中介租房的理解来理解Java的静态代理模式:
首先定义一个租房的接口抽象角色
/*
* 定义给一个租房子的接口
*/
public interface Rent {
public void rent();
}
定义一个房东类 ⇒ ⇒ 真实角色,它继承了实现了抽象角色定义的行为
/*
* 定义房东类,有一个租房子的方法
*/
public class Landlord implements Rent {
@Override
public void rent() {
System.out.println("房东出租房子");
}
}
定义一个中介类 ⇒ ⇒ 代理角色,其内部持有一个房东的引用。
/*
* 中介类,由于你找不到房主,因此你只能找中介帮你租房子
* 因此他也有一个租房子的方法,中介不是活雷锋,因此它会在
* 执行租房方法的时候进行一些与租房本相关的利益活动
*/
public class Agency implements Rent {
//代理角色持有对真实角色的引用,相当于中介手中的房源
private Landlord landlord;
/*
* 中介的租房行为
*/
@Override
public void rent() {
this.before();
if(this.landlord==null) {
landlord = new Landlord();
}
landlord.rent();
this.after();
}
/*
* 中介自己的行文
*/
public void before() {
System.out.println("查找房源");
}
/*
* 中介自己的行文
*/
public void after() {
System.out.println("索要中介费");
}
}
一个测试类:
public class Person {
public static void main(String[] args) {
/*
* 找不到房源,因此只能求助中介租房
*/
Agency agency = new Agency();
agency.rent();
}
}
结果为:
查找房源
房东出租房子
索要中介费
从上面可以看出,每一个真实角色就需要一个代理角色,如果用静态代理的话,会导致类的急剧膨胀,因此显示了动态代理的必要性。
下面看一个动态代理类的实例,其中定义了两个真实角色的类,只要修改一下真实角色即可实现代理类对多个真实类的代理。
- 首先定义一个接口
package com.org.dynamicProxy;
/*
* 抽象角色类,定义一些方法
*/
public interface Subject {
public void dosomething() ;
}
- 定义两个真实角色
package com.org.dynamicProxy;
public class RealSubject1 implements Subject {
@Override
public void dosomething() {
System.out.println("这个方法来自于RealSubject1");
}
}
package com.org.dynamicProxy;
public class Realsubject2 implements Subject {
@Override
public void dosomething() {
System.out.println("这个方法来自于RealSubject2");
}
}
- handler类
package com.org.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class CommonInvocationHandler implements InvocationHandler{
/*
* target变量持有真实角色对象的应用,因为动态代理类可以
* 代理所有对象,因此定义为Object类型的。
*/
private Object target;
public void setTarget(Object target) {
this.target = target;
}
public CommonInvocationHandler() {
}
public CommonInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*
* 1、这里相当于反射中调用method方法来执行,相当于
* method.invoke(对象,new Object[]{参数})
* 只不过java底层已经为我们完成了创建method的过程。
* 2、定义一个result只是增强通用性,我们定义的类的方法并没有返回值
*/
Object result = method.invoke(target, args);
return result;
}
}
测试类:
package com.org.dynamicProxy;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
RealSubject1 realSubject1 = new RealSubject1();
/*
* 生成handler
*/
CommonInvocationHandler handler = new CommonInvocationHandler();
handler.setTarget(realSubject1);
Subject proxy = null;
/*
* 1、生成代理类的实例,proxy相当于前面的中介类生成的实例
* 动态代理与静态代理不太相同的是,静态代理中代理类会直接去执行行为
* 但是在动态代理中,代理对象将执行行为这项操作又委托给hanler去做了
* 2、newProxyInstance是生成代理实例的方法其中第一个参数为类加载器,
* 我们写接口的类加载器就行
* 第二个参数为代理类要实现接口的列表
* 第三个参数为hanlder
*/
proxy = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[] {Subject.class}, handler);
/*
* 执行行为
*/
proxy.dosomething();
System.out.println("-----------------------------------------");
/*
* 代理另一个对象
*/
Realsubject2 realsubject2= new Realsubject2();
handler.setTarget(realsubject2);
/*
* 创建代理类的实例
*/
proxy = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[] {Subject.class}, handler);
proxy.dosomething();
}
}
执行结果
这个方法来自于RealSubject1
-----------------------------------------
这个方法来自于RealSubject2