proxy模式

来源:互联网 发布:辨别产品真假软件 编辑:程序博客网 时间:2024/05/22 06:14

一、定义:为其他对象提供一种代理以控制对这个对象的访问。

二、场景:

(1)系统里有一个BUG,客户发现后,找到支持人员,再由支持人员找到对应的开发。首先找到支持人员,支持人员判断是不是系统BUG可以加一些判断,然后处理由开发人员具体处理,解决以后支持人员又告诉客户你的问题我解决了。

(2)你去超市买东西,其实东西是由工厂生产的,超市就是你和工厂之间的代理。

三、分析:

Spring AOP 声明式事物管理 就是这个应用,代理其实就是“我有前边作点事,我有后边作点事,中间你在作”

一般体现在对于,权限、日志、执行时间等

四、静态代理与动态代理

静态代理:分为聚合和继承

聚合一定比继承好,对于代理的扩展性强。但是静态代理必须知道对于那个需要代理。那如果有许多需要代理,那我需要写很多代理类。

动态代理:对任何类动态的生成代理对象。在内存中生成一份字节码。

五、类图

静态代理代码


public interface Moveable {void move();}

public class Tank implements Moveable {@Overridepublic void move() {System.out.println("TanK moving........");}}

public class TanklogProxy implements Moveable {private Moveable t;public TanklogProxy(Moveable t) {super();this.t = t;}@Overridepublic void move() {System.out.println("start move........");t.move();System.out.println("end move......");}}

public class TanktimeProxy implements Moveable {private Moveable t;public TanktimeProxy(Moveable t) {super();this.t = t;}@Overridepublic void move() {long time1 = System.currentTimeMillis();System.out.println("time1=" + time1);t.move();long time2 = System.currentTimeMillis();System.out.println("time2=" + time2);System.out.println("运行时间为:" + (time2 - time1));}}

public class TestTank {public static void main(String[] args) {Tank t = new Tank();Moveable move = new TanktimeProxy(t);Moveable movet = new TanklogProxy(move);movet.move();}}

动态代理代码:

public interface InvocationHandler {          void invoke(Object o,Method m);  }

public class LogInvocationHandler implements InvocationHandler {private Object target;public LogInvocationHandler(Object target) {super();this.target = target;}@Overridepublic void invoke(Object o, Method m) {System.out.println("Tank start...........");try {m.invoke(target);} catch (Exception e) {e.printStackTrace();}System.out.println("Tank stop..............");}}

public interface Moveable {void move();}

public  class Tank implements Moveable{        @Override      public void move() {          int a = 5;          int b = 6;          int c = 0;          int d = 0;          for (int i = 0; i < 1000; i++) {              d = i;          }          c = ((a+b)/2)*12;          System.out.println("TanK moving..Tank 的速度是"+c);            }  }

public class Proxy {public static Object newProxyIntenct(Class infac, InvocationHandler h)throws Exception {String br = "\r\n";String methString = "";Method[] method = infac.getMethods();for (Method m : method) {methString = "  @Override" + br + "   public void " + m.getName()+ "() {" + br + "       try {" + br + "       Method md ="+ infac.getName() + ".class.getMethod(\"" + m.getName()+ "\");" + br + "       h.invoke(this,md);" + br+ "       }catch (Exception e){ " + br+ "           e.printStackTrace();" + br + "       }" + br+ "   }";}String src = "package "+infac.getPackage().getName()+";" + br+ "import java.lang.reflect.Method;" + br+ "public class $Proxy implements " + infac.getName() + "{"+ br + "   private InvocationHandler h;"+ br + "   public $Proxy(InvocationHandler h) {" + br+ "       super();" + br + "       this.h = h;" + br + "   }"+ br + br + methString + br + "}";MakFileUtil.createFile("D:/src/doproxy");// 生成java文件String fileName = "D:\\src\\doproxy\\$Proxy.java";System.out.println(fileName);File file = new File(fileName);FileWriter fWriter = new FileWriter(file);fWriter.write(src);fWriter.flush();fWriter.close();// 生成class文件,jdk6提供的工具类JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();// System.out.println(compiler.getClass().getName());StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);Iterable units = fileManager.getJavaFileObjects(fileName);CompilationTask task = compiler.getTask(null, fileManager, null, null,null, units);task.call();fileManager.close();// 装载到内存,生成新对象URL[] urls = new URL[] { new URL("file:/" + "D:\\src\\") };URLClassLoader loader = new URLClassLoader(urls);Class c = loader.loadClass("doproxy.$Proxy");// 通过有参的构造器反射生成代理类的实例Constructor ctr = c.getConstructor(InvocationHandler.class);Object obj = (Object) ctr.newInstance(h);return obj;}}

public class MakFileUtil {public static void createFile(String pathstr) throws IOException {// 创建多级目录String path = pathstr;// 为指定字符串构造一个 string tokenizer。 "/"字符是分隔标记的分隔符。分隔符字符本身不作为标记。StringTokenizer st = new StringTokenizer(path, "/");String path1 = st.nextToken() + "/";String path2 = path1;while (st.hasMoreTokens()) {path1 = st.nextToken() + "/";path2 += path1;File inbox = new File(path2);if (!inbox.exists())inbox.mkdir();}}}

public class TestTank {public static void main(String[] args) throws Exception {Tank t = new Tank();Moveable moveable = (Moveable) Proxy.newProxyIntenct(Moveable.class,new TimeInvocationHandler(t));Moveable moveable2 = (Moveable) Proxy.newProxyIntenct(Moveable.class,new LogInvocationHandler(moveable));moveable2.move();}}

代理模式装饰者模式的区别

装饰模式应该为所装饰的对象增强功能;代理模式对代理的对象施加控制,并不提供对象本身的增强功能

二者的实现机制确实是一样的,可以看到他们的实例代码重复是很多的。但就语义上说,这两者的功能是相反的,模式的一个重要作用是简化其他程序员对你程序的理解,


原创粉丝点击