proxy模式

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

二、场景:

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

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

三、分析:

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

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

四、静态代理与动态代理

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

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

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

五、类图

静态代理代码


public interface Moveable {
	void move();
}

public class Tank implements Moveable {

	@Override
	public void move() {
		System.out.println("TanK moving........");
	}

}

public class TanklogProxy implements Moveable {
	private Moveable t;

	public TanklogProxy(Moveable t) {
		super();
		this.t = t;
	}

	@Override
	public 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;
	}

	@Override
	public 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;
	}

	@Override
	public 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();
	}
}

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

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

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


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值