Java设计模式之代理模式

来源:互联网 发布:p2p网贷软件系统 编辑:程序博客网 时间:2024/05/29 18:08

代理模式(proxy)

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

优点:
能生成任意接口的代理对象,实现任意的代理

适用:
1. 控制对一个对象的访问权限,用于对象有权限设置的时候
2. 动态添加日志记录

这里写图片描述

静态代理:

/** *移动接口 */public interface Moveable {    public void move(); }
/** * 被代理类 */public class Tank implements Moveable{    public void move() {        System.out.println("坦克正在开了...");    }}
/** * 坦克人代理类 */public class TankPersonProxy implements Moveable{    Moveable v;  // 聚合    public TankPersonProxy(Moveable v){        this.v = v;    }    public void move() {        System.out.println("坦克里有人上了...");        v.move();        System.out.println("坦克里有人下了...");    }}
/** * 坦克时间代理类 */public class TankTimeProxy implements Moveable{    Moveable v;  // 聚合    public TankTimeProxy(Moveable v){        this.v = v;    }    public void move() {        System.out.println("坦克准备开了...");        v.move();        System.out.println("坦克停下来了...");    }}
/** * 代理模式(静态代理)的测试 */public class Client {    public static void main(String[] args) {        Moveable m = new Tank();        TankTimeProxy tp = new TankTimeProxy(m);        //TankPersonProxy pp = new TankPersonProxy(tp);        tp.move();    }}

动态代理模式1:

public interface Moveable {    void move();}
/** * 被代理类 */public class Tank implements Moveable {    public void move() {        System.out.println("Tank Moving...");        try {            Thread.sleep(new Random().nextInt(10000));        } catch (InterruptedException e) {            e.printStackTrace();        }       }   }
/** * 动态生成代理对象的类 * (只能生成实现了Moveable接口的代理对象) */public class Proxy {    public static Object newProxyInstance() throws Exception{        String rt = "\r\n";        String src =             "package com.hin.proxy_2;" +  rt +            "public class TankTimeProxy implements Moveable {" + rt +            "    public TankTimeProxy(Moveable t) {" + rt +            "        super();" + rt +            "        this.t = t;" + rt +            "    }" + rt +            "    Moveable t;" + rt +            "    @Override" + rt +            "    public void move() {" + rt +            "        long start = System.currentTimeMillis();" + rt +            "        System.out.println(\"starttime:\" + start);" + rt +            "        t.move();" + rt +            "        long end = System.currentTimeMillis();" + rt +            "        System.out.println(\"time:\" + (end-start));" + rt +            "    }" + rt +            "}";        String fileName = System.getProperty("user.dir")                             + "/src/com/hin/proxy_2/TankTimeProxy.java";        File f = new File(fileName);        FileWriter fw = new FileWriter(f);        fw.write(src);        fw.flush();        fw.close();        //compile        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);        Iterable units = fileMgr.getJavaFileObjects(fileName);        CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);        t.call();        fileMgr.close();        //load into memory and create an instance        URL[] urls = new URL[] {new URL("file:/" + System.getProperty("user.dir") +"/src")};        URLClassLoader ul = new URLClassLoader(urls);        Class c = ul.loadClass("com.hin.proxy_2.TankTimeProxy");        System.out.println(c);        Constructor ctr = c.getConstructor(Moveable.class);  // 获得参数为Moveable的构造方法        Moveable m = (Moveable)ctr.newInstance(new Tank());        //m.move();        return m;    }}
/** * 动态代理模式的测试_1 (只能对指定的对象,指定的接口方法,实现指定的代理;在Proxy中生成指定的接口的代理对象) * (在静态代理中,代理对象是要写出来的;而在动态代理中,不用知道代理对象的名字,要的那个代理对象直接帮你产生) */public class Client {    public static void main(String[] args) throws Exception {        //Tank t = new Tank();        Moveable m = (Moveable)Proxy.newProxyInstance();        m.move();    }}

动态代理模式2:

public interface Moveable {    void move();}
/** * 被代理类 */public class Tank implements Moveable {    public void move() {        System.out.println("Tank Moving...");        try {            Thread.sleep(new Random().nextInt(10000));        } catch (InterruptedException e) {            e.printStackTrace();        }       }   }
/** * 动态生成代理对象的类(传入接口) * (能生成任意接口的代理对象) */public class Proxy {    public static Object newProxyInstance(Class infce) throws Exception{        String methodStr = "";        String rt = "\r\n";        Method[] methods = infce.getMethods();        for(Method m : methods){  // 编历接口里面的方法            methodStr += "    @Override" + rt +                         "    public void " + m.getName() + "() {" + rt +                         "        long start = System.currentTimeMillis();" + rt +                         "        System.out.println(\"starttime:\" + start);" + rt +                         "        t." + m.getName() + "();" + rt +                         "        long end = System.currentTimeMillis();" + rt +                         "        System.out.println(\"time:\" + (end-start));" + rt +                         "    }" + rt +                         "}";                   }        String src =             "package com.hin.proxy_3;" +  rt +            "public class TankTimeProxy implements " + infce.getName() + " {" + rt +            "    public TankTimeProxy(Moveable t) {" + rt +            "        super();" + rt +            "        this.t = t;" + rt +            "    }" + rt +            "    Moveable t;" + rt +            methodStr;   // 加上接口里的方法        String fileName = System.getProperty("user.dir")                             + "/src/com/hin/proxy_3/TankTimeProxy.java";        File f = new File(fileName);        FileWriter fw = new FileWriter(f);        fw.write(src);        fw.flush();        fw.close();        //compile        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);        Iterable units = fileMgr.getJavaFileObjects(fileName);        CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);        t.call();        fileMgr.close();        //load into memory and create an instance        URL[] urls = new URL[] {new URL("file:/" + System.getProperty("user.dir") +"/src")};        URLClassLoader ul = new URLClassLoader(urls);        Class c = ul.loadClass("com.hin.proxy_3.TankTimeProxy");        System.out.println(c);        Constructor ctr = c.getConstructor(Moveable.class);  // 获得参数为Moveable的构造方法        Object m = ctr.newInstance(new Tank());        //m.move();        return m;    }}
/** * 动态代理模式的测试_3 (能生成任意接口的代理对象) * (在静态代理中,代理对象是要写出来的;而在动态代理中,不用知道代理对象的名字,要的那个代理对象直接帮你产生) */public class Client {    public static void main(String[] args) throws Exception {        //Tank t = new Tank();        Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class);        m.move();    }}

动态代理3:

public interface Moveable {    void move();}
/** * 被代理类(坦克) */public class Tank implements Moveable {    public void move() {        System.out.println("Tank Moving...");        try {            Thread.sleep(new Random().nextInt(10000));        } catch (InterruptedException e) {            e.printStackTrace();        }       }   }
/** * 动态生成代理对象的类(传入接口和处理器) * (能生成任意接口的代理对象,实现任意的代理) */public class Proxy {    public static Object newProxyInstance(Class infce, InvocationHandler h) throws Exception{        String methodStr = "";        String rt = "\r\n";        Method[] methods = infce.getMethods();        for(Method m : methods){  // 编历接口里面的方法            methodStr += "    @Override" + rt +                         "    public void " + m.getName() + "() {" + rt +                         "        try {" + rt +                         "          Method md = " + infce.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +                         "          h.invoke(this, md);" + rt +                         "        }catch(Exception e) {e.printStackTrace();}" + rt +                         "    }" + rt +                         "}";                   }        String src =             "package com.hin.proxy_4;" +  rt +            "import java.lang.reflect.Method;" + rt +            "public class $proxy1 implements " + infce.getName() + " {" + rt +            "    public $proxy1(InvocationHandler h) {" + rt +            "        this.h = h;" + rt +            "    }" + rt +            "    com.hin.proxy_4.InvocationHandler h;" + rt +            methodStr;  // 加上接口里的方法        String fileName = System.getProperty("user.dir")                             + "/src/com/hin/proxy_4/$proxy1.java";        File f = new File(fileName);        FileWriter fw = new FileWriter(f);        fw.write(src);        fw.flush();        fw.close();        //compile        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);        Iterable units = fileMgr.getJavaFileObjects(fileName);        CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);        t.call();        fileMgr.close();        //load into memory and create an instance        URL[] urls = new URL[] {new URL("file:/" + System.getProperty("user.dir") +"/src")};        URLClassLoader ul = new URLClassLoader(urls);        Class c = ul.loadClass("com.hin.proxy_4.$proxy1");        System.out.println(c);        Constructor ctr = c.getConstructor(InvocationHandler.class);  // 获得参数为Moveable的构造方法        Object m = ctr.newInstance(h);        //m.move();        return m;    }}
/** * 处理器接口 */public interface InvocationHandler {    /**     * @param o  代理对象     * @param m       */    public void invoke(Object o, Method m);}
/** * 动态代理模式的测试_4 (可以对任意的对象、任意的接口方法,实现任意的代理) * (目前只能实现一层代理,还没完成叠加的代理) * (在静态代理中,代理对象是要写出来的;而在动态代理中,不用知道代理对象的名字,要的那个代理对象直接帮你产生) */public class Client {    public static void main(String[] args) throws Exception {        Tank t = new Tank();  // 被代理对象        InvocationHandler h = new TimeHandler(t);  // 时间上的代理        Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class, h);        m.move();    }}
原创粉丝点击