Java23种设计模式详解1——代理模式

1 介绍

为其他对象提供一个代理以控制对某个真实对象的访问,如Spring的AOP,Nginx的反向代理和Hibernate中PO(Persistant Object 持久化对象)字节码的生成等。优点可以降低系统的耦合度,缺点是需要额外的工作,而且有些代理模式的实现比较复杂。根据代理的创建时期,可划分为静态代理和动态代理两种。

2 静态代理

在程序运行前代理类的.class文件就已经存在了。

2.1 UML图分析

GoogleSearch是一个公共的接口,通过其实现海外服务器ForeignDerver可以直接访问谷歌搜索,类ProxyServer虽然也是GoogleSearch接口的实现,但实际上是用户侧的代理服务器,它可以从ForeignDerver处间接访问谷歌搜索。类StaticProxyDemo是测试类。

2.2 源码

1)创建公共接口

2)接口实现类

public class ForeignServer implements GoogleSearch {

	@Override
	public void useGoogleSearch() {
			System.out.println("Connect successfully!");
	}

}

3)代理类

public class ProxyServer implements GoogleSearch {
	
	private ForeignServer foreignServer;
	
	@Override
	public void useGoogleSearch() {
		if(foreignServer == null){
			foreignServer = new ForeignServer();
		}
		foreignServer.useGoogleSearch();
	}
}

4)测试类

public class StaticProxyDemo {
	
	public static void main(String[] args) {
		GoogleSearch googleSearch = new ProxyServer();
		googleSearch.useGoogleSearch();
	}
}

2.3 测试结果

2.4 缺点

如果要想为多个类进行代理,则需要建立多个代理类,维护难度加大。通俗得讲,此时的代理服务器是专有服务器,只能用于访问谷歌相关产品,那么要访问FB的产品又需要不同的代理服务器,这样下来就需要一大堆海外服务器。

3 动态代理

动态代理是在程序运行时运用反射机制动态创建而成。相对于静态代理,其只需要一个代理类即可,即只需要一个通用服务器即可访问n多海外网站。

3.1 UML图分析

相对静态代理,ProxyServer只需要实现InvocationHandler接口。getProxy()方法是利用反射技术,在JVM运行时获取一个实现了指定接口的代理类的实例。而invoke()是在代理实例上处理方法调用并返回结果。

3.2 源码

1)创建接口

2)接口实现类

public class ForeignServer implements GoogleSearch {

	@Override
	public void useGoogleSearch() {
			System.out.println("Connect successfully!");
	}

}

3)代理类

public class ProxyServer implements InvocationHandler {
	private Object obj;
	
	public ProxyServer(Object obj) {
		this.obj = obj;
	}
	
	/**
	 * 返回一个实现了指定接口的类的实例
	 * @return 
	 */
	public Object getProxy(){
		return Proxy.newProxyInstance(Thread.currentThread()  
                .getContextClassLoader(), obj.getClass().getInterfaces(), this);
	}

	/**
	 * 在代理实例上处理方法调用并返回结果
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = method.invoke(obj, args);
		return result;
	}
}

4)测试类

public class DynamicProxyDemo {
	
	public static void main(String[] args) {
		GoogleSearch foreignSearch = new ForeignServer();
		ProxyServer proxyServer = new ProxyServer(foreignSearch);
		GoogleSearch proxySerch =  (GoogleSearch)proxyServer.getProxy();
		proxySerch.useGoogleSearch();
	}
}

3.3 测试结果

3.4 缺点

Java动态代理要求被代理的类必须实现接口,有很强的局限性,可以通过CGLIB动态代理的方式解决。

原创文章 32 获赞 12 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_35469756/article/details/79517828