代理模式
依照java万物皆对象的思想,代理模式自然也可以往现实中作映射。那么代理模式是什么呢?其实就是我们身边常见的——中介。
当我们想要买会跑,会飞的车子时。我们可以自己去到各个4s店去看车,也可以把我们的要求委托给中介,由中介把合适的车子卖给我们。
代理模式定义:为其他它对象提供代理,对原对象的访问进行控制,并可以去除或增加一些服务。
代理模式结构:
interface :抽象角色,一个接口,由原对象和代理对象共同继承。
primaryModel: 原对象角色,原对象,一个实现了接口的类。
proxy: 代理角色,代理对象,内部对原对象进行引用,提供与原对象相对的接口,以完全代替原对象,并能对原对象的功能进行拓展。
静态代理:由开发者定义,程序运行前就已编译。
优点:扩展原对象功能,不入侵源代码。
缺点:在给不同的对象拓展相对的代码逻辑时,也要分别创建代理类,导致需要编写重复的功能代码。
1.由聚合实现:
/** * @Author SZF * * @Date 2018-08-09 * */ //抽象接口 public interface WantCar { void canRun(); void canFly(); } //原类 public class PrimaryCar implements WantCar { public void canRun() { System.out.println("I can run!"); } public void canFly() { System.out.println("I can fly!"); } } //聚合代理 public class ProxyCar extends PrimaryCar{ private PrimaryCar pcar; public ProxyCar (PrimaryCar pcar) { super(); this.pcar=pcar; } public void canRun() { System.out.println("I can run!"); System.out.println("I can run at Moon!");//拓展 } public void canFly() { System.out.println("I can fly!"); System.out.println("I can fly at Mars");//拓展 } } //使用 PrimaryCar pcar=new PrimaryCar(); WantCar wcar=new ProxyCar(pcar); wcar.canRun(); wcar.canFly();
2.由继承实现:
/**
* @Author SZF
*
* @Date 2018-08-09
*
*/
//抽象接口
public interface WantCar() {
void canRun();
void canFly();
}
//原类
public class PrimaryCar implements PrimaryCar {
public void canRun() {
System.out.println("I can run!");
}
public void canFly() {
System.out.println("I can fly!");
}
}
//继承代理
public class ProxyCar implements WantCar{
@Override
public void canRun() {
super.canRun();
System.out.println("I can run at Moon!");//拓展
}
public void canFly() {
super.canFly();
System.out.println("I can fly at Mars");//拓展
}
}
//使用
ProxyCar pcar=new ProxyCar();
pcar.canRun();
pcar.canFly();
以上两种实现方式相比较,继承式不够灵活。举个栗子,原类中有1,2两种方法,每种方法程序执行先后顺序导致的结果不同。
此时继承式写法就需要编写两个不同的代理类(1,2)(2,1),相比之下,聚合式只需要改变方法的调用顺序就行了。
动态代理:于程序运行期自动创建,为了解决静态代理的缺点而存在。
想要实现动态代理,我们需要java.lang.reflect.InvocationHandler接口和java.lang.reflect.Proxy类的支持
首先我们先了解一下java.lang.reflect.InvcocatioHandler接口:
invocationHandler接口仅定义了一个方法

该方法第一个参数一般指代理类,第二个指被代理的方法,最后一个为该方法的参数
java.lang.reflect.Proxy类即为动态代理类,其主要包含以下内容:
Protected Proxy (invocationHandler h); //构造函数 Static Class getProxyClass (ClassLoader loader,Class[] interfaces)://获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口数组
Static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)://返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。
下面我们来看如何使用动态代理
首先和之前相同的接口,原类。
/** * @Author SZF * * @Date 2018-08-09 * */ //抽象接口 public interface WantCar { void canRun(); void canFly(); } //原类 public class PrimaryCar implements WantCar { public void canRun() { System.out.println("I can run!"); } public void canFly() { System.out.println("I can fly!"); } }
接着定义一个动态代理类,我们动态代理类必须要实现invocationHandler 接口:
public class DynamicProxy implements InvocationHandler{ // 我们要代理的真实对象 private PrimaryCar pCar; // 构造方法,给我们要代理的真实对象赋初值 public DynamicProxy(PrimaryCar pCar) { this.pCar= pCar; } @Override public Object invoke(PrimaryCar pCar, Method method, Object[] args) throws Throwable { // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用 method.invoke(wCar, args); //我们也可以延伸一些自己的方法 System.out.println("I can do anything!"); return null; } }
最后,我们于Client进行调用:
newProxyInstance()具体实现之后再作更深入的讨论。
package test; /** * @Author SZF * * @Date 2018-08-09 * */ public class test { public static void main(String[] args) { PrimaryCar pCar=newprimaryCar(); DynamicProxy dCar=new DynamicProxy(pCar); WantCar wcar=new (WantCar) dCar.newProxyInstance(pCar.getClass().getClassLoader(), pCar.getClass().getInterfaces(),dCar); System.out.println(wcar.run()); } }
输出:
I can run!
I can do anything!
参考:百度百科

浙公网安备 33010602011771号