前言
设计模式分为三大类:
创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式;
结构型模式:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式;
行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式;
代理模式
代理是基本的设计模式之一,提供额外的或不同的操作,代理通常充当中间人的角色,如果用“租房子”来打比方,代理则是中介,首先要明确的是:不论是静态代理还是动
态代理,被代理对象都要有一个实现的接口
静态代理
静态代理的本质是:用户调用目标对象的方法是通过代理对象调用的,其中代理对象中组合了目标对象实现的接口,因此可以在代理对象中调用目标对象的方法。
1. 目标对象实现的接口
package com.oxygen.proxy;/*** 目标对象实现的接口* @date 2018年10月10日*/
public interface TargetInterface { // 接口void method1(); /* public abstract */void method2(String arg);String method3();
}
2. 目标对象
package com.oxygen.proxy;/*** 目标对象* @author Oxygen * @date 2018年10月10日*/
public class Target implements TargetInterface {@Overridepublic void method1() {System.out.println("method1 run ");}@Overridepublic void method2(String arg) {System.out.println("method2 run ");}@Overridepublic String method3() {System.out.println("method3 run ");return "Oxygen";}
}
3. 代理
package com.oxygen.proxy;/*** @author Oxygen* @date 2018年10月10日*/
public class SimpleProxyDemo {public static void consumer(TargetInterface iface) {iface.method1();iface.method2("...");}public static void main(String[] args) {consumer(new Target());consumer(new SimpleProxy(new Target()));}
}class SimpleProxy implements TargetInterface { // 静态代理对象private TargetInterface proxied; //
public SimpleProxy(TargetInterface proxied) {super();this.proxied = proxied;}@Overridepublic void method1() {System.out.println("=====before method1===== "); // 代理对象增强方法的代码
proxied.method1();System.out.println("=====after method1===== "); // 代理对象增强方法的代码
}@Overridepublic void method2(String arg) {System.out.println("=====before method2===== "); // 代理对象增强方法的代码
proxied.method2(arg);System.out.println("=====after method2===== "); // 代理对象增强方法的代码
}@Overridepublic String method3() {System.out.println("method3 run ");return "Oxygen";}
}
4.输出
output:
method1 run
method2 run //直接调用目标对象的方法=====before method1===== //以下是通过代理对象调用目标对象的方法
method1 run
=====after method1===== =====before method2=====
method2 run
=====after method2===== =====before method3===== method3 run =====after method3=====
动态代理
动态代理的本质和静态代理是不同的,不同点如下:
1. 静态代理需要用户写代理对象,而动态代理是JVM在内存中生成代理对象
2. 动态代理的代理对象是通过反射机制调用目标对象的方法,而静态代理是通过在代理对象中组合目标对象实现的接口来实现调用目标对象方法的功能
3. 动态代理的代理对象和目标对象实现了相同的接口
【参考资料】:Java中的反射机制
package com.oxygen.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 动态代理:产生的代理对象是接口的实现类* @author Oxygen* @date 2018年10月10日*/
public class ProxyDemo {public static void main(String[] args) {Target target = new Target();/** 参数讲解:* 1. 被代理对象的类加载器* 2. 被代理对象实现的接口的字节码数组 // 也可以是 new Class[] { TargetInterface.class }* 3. InvocationHandler* 4. 返回值要和接口的字节码数组中的接口类型一致*/TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(Target.class.getClassLoader(),target.getClass().getInterfaces(), new InvocationHandler() {/** InvocationHandler可以理解为一组规范,代理对象proxy调用目标对象几次方法,该方法就执行几次* 此时该方法执行3次,因为proxy调用了3次目标方法method1、2、3* invoke:执行代理对象的方法* proxy:代理对象* method:代码目标对象方法的字节码Method对象* args:被代理对象中方法的参数*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before target method run ");/** invoke():代理对象通过反射调用目标对象的方法* invoke:表示返回的对象,也就是执行完相应目标方法后返回的对象,如果目标方法返回值为void,则invoke为null* new Target():目标对象*/Object invoke = method.invoke(new Target(), args);System.out.println("after target method run");return invoke;}});proxy.method1(); //执行目标方法1proxy.method2("go");//执行目标方法2String result = proxy.method3();//执行目标方法3System.out.println(result);//output: Oxygen,即为method3()的返回值
}
}