Java设计模式之代理模式

代理模式(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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心歌技术

打赏不能超过你的早餐钱!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值