代理模式
定义:通过代理对象访问目标对象;
举个例子来说明代理的作用:明星与经纪人之间就是被代理和代理的关系,明星出演活动的时候,明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)
优点:在目标对象的基础上,扩展额外的功能补充;
代理分类:静态代理和动态代理
静态代理:代理类调用具体被代理类,并扩展额外功能
接口类
public interface Star { public void sing(); }
具体被代理对象类(业务类)
public class Star1 implements Star { @Override public void sing() { System.out.println("Star1 sing"); } }
代理类对象(代理具体对象,并补充额外功能)
public class StarAgent implements Star { Star1 star1 = new Star1(); @Override public void sing() { System.out.println("work start"); star1.sing(); System.out.println("work end"); } public static void main(String[] args) { StarAgent starAgent = new StarAgent(); starAgent.sing(); } }
动态代理:动态代理是在程序运行时通过反射机制动态创建的。主要是用到了java.lang.reflect.Proxy类和InvocationHandler接口
接口类
public interface Subject { public void request(); }
具体被代理对象类1(业务类1)
public class RealSubject1 implements Subject { @Override public void request() { System.out.println("this is RealSubject1"); } }
具体被代理对象类2(业务类2)
public class RealSubject2 implements Subject { @Override public void request() { System.out.println("this is RealSubject2"); } }
代理对象
/** * 代理类 * 内部属性是object类型,实际使用的时候通过该类的构造方法传递进来一个对象 * 此外,该类还实现了invoke方法,该方法中的method。invoke其实就是调用被代理对象的将要执行的方法 * 方法参数是sub,表示该方法从属于sub,通过动态代理类,我们可以在执行真实对象的方法前后加入自己的一些额外方法 */ public class DynamicSubject implements InvocationHandler { // 代理object private Object sub; public DynamicSubject() { } public DynamicSubject(Object o) { this.sub = o; } public void setSub(Object sub) { this.sub = sub; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("invoke before " + method); Object object = method.invoke(sub, args); System.out.println("invoke after " + method); return null; } }
测试类(调用类)
public class Client { public static void main(String[] args) { DynamicSubject handler = new DynamicSubject(); handler.setSub(new RealSubject1()); //生成class Class<?> classType = handler.getClass(); //动态生成代理 Subject subject1 = (Subject)Proxy.newProxyInstance(classType.getClassLoader(), new Class[]{Subject.class}, handler); subject1.request(); handler.setSub(new RealSubject2()); Subject subject2 = (Subject)Proxy.newProxyInstance(classType.getClassLoader(), new Class[]{Subject.class}, handler); subject2.request(); } }