设计模式(六)代理模式
——核心作用:通过代理,控制对对象的访问,可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,从而实现将统一流程代码放到代理类中处理,调用这个方法后做后置处理。
——AOP(Aspect Oriented Programming面向切面编程)的核心实现机制
——核心角色:
抽象角色:定义代理角色和真实角色的公共对外方法。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
关注真正的业务逻辑。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附 加自己的操作。
将统一的流程控制放到代理角色中处理。
——应用场景:
安全代理:屏蔽对真实角色的直接访问。
远程代理:通过代理类处理进程方法调用(RMI)。
延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象。
(比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有100MB,在打开文件时不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用Proxy来进行大图片的打开)
——分类:
静态代理(静态定义代理类)
动态代理(动态生成代理类)
-
- JDK自带的动态代理
- Javaassist字节码操作库实现
- CGLIB
- ASM(底层使用指令,可维护性较差)
静态代理:
1. 定义一个Star接口
1 package com.ztq.proxy.staticProxy; 2 3 public interface Star { 4 /*** 5 * 面谈 6 */ 7 void confer(); 8 9 /*** 10 * 签合同 11 */ 12 void signContract(); 13 14 /*** 15 * 订票 16 */ 17 void bookTicket(); 18 19 /*** 20 * 唱歌 21 */ 22 void sing(); 23 24 /*** 25 * 收钱 26 */ 27 void collectMoney(); 28 }
2. 定义一个RealStar类
1 package com.ztq.proxy.staticProxy; 2 3 public class RealStar implements Star{ 4 5 @Override 6 public void confer() { 7 System.out.println("RealStar.confer()"); 8 } 9 10 @Override 11 public void signContract() { 12 System.out.println("RealStar.signContract()"); 13 } 14 15 @Override 16 public void bookTicket() { 17 System.out.println("RealStar.bookTicket()"); 18 } 19 20 @Override 21 public void sing() { 22 System.out.println("RealStar.sing()"); 23 } 24 25 @Override 26 public void collectMoney() { 27 System.out.println("RealStar.collectMoney()"); 28 } 29 30 }
3. 定义一个ProxyStar类
1 package com.ztq.proxy.staticProxy; 2 3 public class ProxyStar implements Star{ 4 5 private Star star; 6 7 public ProxyStar(Star star){ 8 super(); 9 this.star = star; 10 } 11 12 @Override 13 public void confer() { 14 System.out.println("ProxyStar.confer()"); 15 } 16 17 @Override 18 public void signContract() { 19 System.out.println("ProxyStar.signContract()"); 20 } 21 22 @Override 23 public void bookTicket() { 24 System.out.println("ProxyStar.bookTicket()"); 25 } 26 27 @Override 28 public void sing() { 29 star.sing(); 30 } 31 32 @Override 33 public void collectMoney() { 34 System.out.println("ProxyStar.collectMoney()"); 35 } 36 37 }
4. 定义一个客户端调用
1 package com.ztq.proxy.staticProxy; 2 3 public class Client { 4 public static void main(String[] args) { 5 Star real = new RealStar(); 6 Star proxy = new ProxyStar(real); 7 8 proxy.confer(); 9 proxy.signContract(); 10 proxy.bookTicket(); 11 proxy.sing(); 12 proxy.collectMoney(); 13 } 14 }
运行结果:
ProxyStar.confer()
ProxyStar.signContract()
ProxyStar.bookTicket()
RealStar.sing()
ProxyStar.collectMoney()
UML图:
动态代理相比于静态代理的优点:抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样我们可以更加灵活和统一的处理众多的方法。
JDK自带的动态代理:
java.lang.reflect.Proxy 作用:动态生成代理类和对象
java.lang.reflect.InvocationHandler(处理器接口)
可以通过invoke方法实现对真实角色的代理访问。
每次通过Proxy生成代理类对象时都要指定对应的处理器对象。
Star接口、RealStar类与静态代理一样,此处省略。
定义一个StarHandler类
1 package com.ztq.proxy.dynamicProxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class StarHandler implements InvocationHandler{ 7 8 Star realStar; 9 10 public StarHandler(Star realStar) { 11 super(); 12 this.realStar = realStar; 13 } 14 15 @Override 16 public Object invoke(Object proxy, Method method, Object[] args) 17 throws Throwable { 18 Object object = null; 19 System.out.println("真正的方法执行前"); 20 System.out.println("面谈,签合同,预付款,订机票"); 21 if(method.getName().equals("sing")){ 22 object = method.invoke(realStar, args); 23 } 24 System.out.println("真正的方法执行后"); 25 System.out.println("收尾款"); 26 return object; 27 } 28 29 }
定义一个客户端调用类
1 package com.ztq.proxy.dynamicProxy; 2 3 import java.lang.reflect.Proxy; 4 5 public class Client { 6 public static void main(String[] args) { 7 Star realStar = new RealStar(); 8 StarHandler handler = new StarHandler(realStar); 9 Star proxy = (Star)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Star.class}, handler); 10 11 proxy.bookTicket(); 12 proxy.sing(); 13 } 14 }
运行结果
真正的方法执行前
面谈,签合同,预付款,订机票
真正的方法执行后
收尾款
真正的方法执行前
面谈,签合同,预付款,订机票
RealStar.sing()
真正的方法执行后
收尾款