1.什么是代理模式
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
2.代理模式的优缺点
优点: 1、职责清晰。 2、高扩展性。 3、智能化。
缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
3.应用场景
1、Windows 里面的快捷方式
2、买火车票不一定在火车站买,也可以去代售点
按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理
注意:
1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制
4.UML类图与实现
4.1简单的代理模式实现
Image.java public interface Image { void display(); } RealImage.java public class RealImage implements Image { private String fileName; public RealImage(String fileName){ this.fileName = fileName; loadFromDisk(fileName); } @Override public void display() { System.out.println("Displaying " + fileName); } private void loadFromDisk(String fileName){ System.out.println("Loading " + fileName); } } ProxyImage.java public class ProxyImage implements Image{ private RealImage realImage; private String fileName; public ProxyImage(String fileName){ this.fileName = fileName; } @Override public void display() { if(realImage == null){ realImage = new RealImage(fileName); } realImage.display(); } } ProxyPatternDemo.java public class ProxyPatternDemo { public static void main(String[] args) { Image image = new ProxyImage("test_10mb.jpg"); // 图像将从磁盘加载 image.display(); System.out.println(""); // 图像不需要从磁盘加载 image.display(); } }
4.2JDK 自带的动态代理
java.lang.reflect.Proxy:生成动态代理类和对象;
java.lang.reflect.InvocationHandler(处理器接口):可以通过invoke方法实现
Subject.java public interface Subject { public int sellBooks(); public String speak(); } RealSubject.java public class RealSubject implements Subject{ @Override public int sellBooks() { System.out.println("卖书"); return 1 ; } @Override public String speak() { System.out.println("说话"); return "张三"; } } MyInvocationHandler.java public class MyInvocationHandler implements InvocationHandler { /** * 因为需要处理真实角色,所以要把真实角色传进来 */ Subject realSubject ; public MyInvocationHandler(Subject realSubject) { this.realSubject = realSubject; } /** * * @param proxy 代理类 * @param method 正在调用的方法 * @param args 方法的参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("调用代理类"); if(method.getName().equals("sellBooks")){ int invoke = (int)method.invoke(realSubject, args); System.out.println("调用的是卖书的方法"); return invoke ; }else { String string = (String) method.invoke(realSubject,args) ; System.out.println("调用的是说话的方法"); return string ; } } } Main.java public class Client { public static void main(String[] args) { //真实对象 Subject realSubject = new RealSubject(); MyInvocationHandler myInvocationHandler = new MyInvocationHandler(realSubject); //代理对象 Subject proxyClass = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Subject.class}, myInvocationHandler); proxyClass.sellBooks(); proxyClass.speak(); } }