Java设计模式之代理模式

本文深入探讨了代理模式在软件设计中的应用,包括静态代理和动态代理的概念、实现方式及其优势。通过具体实例,如浏览器访问外网时使用代理服务器,解释了代理模式如何在不直接访问目标对象的情况下,通过中间代理实现目标功能,并在此过程中添加额外的逻辑,如日志记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平时在公司内网使用浏览器时,一般要设计代理服务器。因为我们的浏览器无法直接访问外网,而代理服务器能,因此将请求发送给代理服务器,由代理服务器替我们访问网页并返回结果。

代理模式原理也是这样,不直接访问目标对象,而是中间加一个代理,再由代理访问真正的对象,当然代理一定实现了某些逻辑,否则就没有必要使用代理了。

1、静态代理

接口:

public interface MyInterface {
	public boolean saySomething();

	public boolean doSomeThint();
}

接口实现:

public class MyImpl implements MyInterface {

	@Override
	public boolean saySomething() {
		System.out.println("MyImpl:saySomething()");
		return true;
	}

	@Override
	public boolean doSomeThint() {
		System.out.println("MyImpl:doSomething()");
		return true;
	}

}

静态代理实现:

public class StaticProxy {
	
	// 增加了日志功能的代理类
	private static class LogProxy implements MyInterface {

		private MyInterface myInterface;

		public LogProxy(MyInterface myInterface) {
			this.myInterface = myInterface;
		}

		public boolean saySomething() {
			System.out.println("BeforeLog:saySomething");
			boolean tmp = myInterface.saySomething();
			System.out.println("AfterLog:saySomething");
			return tmp;
		}

		public boolean doSomeThint() {
			System.out.println("BeforeLog:doSomething");
			boolean tmp = myInterface.doSomeThint();
			System.out.println("AfterLog:doSomething");
			return tmp;
		}

	}

	public static void main(String[] args) {
		MyInterface inf = new LogProxy(new MyImpl());
		inf.saySomething();
		inf.doSomeThint();
	}

}

LogProxy是代理类,目的是在访问接口中的方法时,在方法的前后加上日志,无需修改原始实现。使用静态内部类是为了控制类的可见性。

上边的实现方法与装饰器模式的实现一模一样,只是说法不一样而已。

2、动态代理

以上实现方式中,LogProxy只能代理MyInterface接口,它们的这种关系是编译阶段就确定的,所以称为静态代理。如果MyInterface接口修改了,那么相应的LogProxy代理也要跟着修改。

LogProxy的逻辑是在方法的前后加上日志,它应该是独立的逻辑,与具体的接口没有关系。Java中的动态代理机制就能实现这种解耦,LogProxy到底代理谁是在运行阶段确定的,因此是动态的,代码如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DaynamicProxy {

	// 增加了日志功能的代理类
	static class LogProxy implements InvocationHandler {

		private Object target;

		public LogProxy(Object target) {
			this.target = target;
		}

		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			System.out.println(proxy.getClass().getName());
			System.out.println("BeforeLog:" + method.getName());
			Object tmp = method.invoke(target, args);
			System.out.println("AfterLog:" + method.getName());
			return tmp;
		}
	}

	public static void main(String[] args) {
		// 到底代理谁在运行阶段指定
		InvocationHandler h = new LogProxy(new MyImpl());
		MyInterface inf = (MyInterface) Proxy.newProxyInstance(LogProxy.class.getClassLoader(),
				MyImpl.class.getInterfaces(), h);
		inf.saySomething();
		inf.doSomeThint();
	}
}

注意LogProxy实现了InvocationHandler接口,只需实现invoke一个方法就可以。
注意Proxy.newProxyInstance方法的调用,得到的MyInterface接口是被代理过的,效果与前边的实现方案相同。

不同点就是,现在LogProxy是独立的逻辑,不与具体的接口、具体的类相关,也就是它可以代理任何符合条件的类。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值