代理模式分为静态代理、动态代理模式,其目的是为某个对象提供间接的访问方式,不去直接访问对象,达到了解耦的作用,以及增强的作用。
静态代理

这是从百度百科摘取下来的
Subject:可以是抽象类或者是接口。
RealSubject:是Subject的实现类,真正的逻辑功能在这个类中完成,也就是被代理类(委托类)。
Proxy:就是代理类,也实现了Subject中的方法,但是不像RealSubject一样实现逻辑,而是增加一些扩展功能,达到增强的作用。通过Proxy类访问RealSubject,客户端与RealSubject起到解耦作用。
下面看看静态代理的示例
//用户表接口(Subject)public interface UserManager {//保存用户void saveUser(User user);//删除用户void delUser(User user);//更新用户void updUser(User user);}
//用户实现类(被代理类)public class RealUserManagerImp implements UserManager {@Overridepublic void saveUser(User user) {System.out.println("被代理类执行了用户保存");}@Overridepublic void delUser(User user) {System.out.println("被代理类执行了用户删除");}@Overridepublic void updUser(User user) {System.out.println("被代理类执行了用户更新");}}
//用户实现类(代理类)public class ProxyUserManagerImp implements UserManager {private UserManager userManager;public ProxyUserManagerImp(UserManager userManager) {this.userManager = userManager;}@Overridepublic void saveUser(User user) {System.out.println("---连接数据库");System.out.println("---打开事务");userManager.saveUser(user);System.out.println("---提交");System.out.println("----关闭事务");System.out.println("----关闭数据库连接");}@Overridepublic void delUser(User user) {System.out.println("---连接数据库");System.out.println("---打开事务");userManager.delUser(user);System.out.println("---提交");System.out.println("----关闭事务");System.out.println("----关闭数据库连接");}@Overridepublic void updUser(User user) {System.out.println("---连接数据库");System.out.println("---打开事务");userManager.updUser(user);System.out.println("---提交");System.out.println("----关闭事务");System.out.println("----关闭数据库连接");}}
public class ClientDemo {public static void main(String[] args) {//其实后来写「装饰模式」的时候,区分装饰跟静态代理两种模式,//我觉得在静态代理这里,客户端调用代理的时候,不应该传这个具体的RealUserManagerImp实例//应该在代理类的构造方法中去创建这个被代理类//达到一种客户端「无感」调用 -- 记2018-12-21UserManager userManager = new ProxyUserManagerImp(new RealUserManagerImp());userManager.saveUser(new User());}}

通过上面的示例,我们可以看到是一个数据保存的过程。客户端想保存某个用户信息,直接访问代理类的saveUser方法。代理类为被代理类做了数据保存前的操作以及数据保存之后的操作,扩展了保存的功能。
但是静态代理类有个缺点。假设我现在有LogManager,上方的代码得全部敲一遍。一个数据库有20个表呢?是不是就发现就得需要20个代理类?所以就需要动态生成代理类。
下面看示例,UserManager、RealUserManagerImp这两个类原封不动,然后加入下面这个类
//动态代理类public class ProxyUserManagerHandle implements InvocationHandler {//目标对象(例如User\Log等等)private Object targetObject;//通过Proxy类,动态生成代理类,并且创建代理类实例public Object newProxyInstance(Object targetObject) {this.targetObject = targetObject;//第一个参数为目标对象的类加载器//第二个参数为目标对象继承的接口//第三个参数为需要执行哪个handler中invoke的方法return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("---连接数据库");System.out.println("---打开事务");method.invoke(targetObject, args);System.out.println("args:" + args);System.out.println("---提交");System.out.println("----关闭事务");System.out.println("----关闭数据库连接");return null;}}
然后再运行一下客户端
public class ClientDemo {public static void main(String[] args) {ProxyUserManagerHandle pumh = new ProxyUserManagerHandle();UserManager userManagerProxy = (UserManager) pumh.newProxyInstance(new RealUserManagerImp());userManagerProxy.delUser(new User());}}

动态代理与静态代理的区别,前者是在程序运行中的时候创建的,大大减少了应用的代码量,而且jdk在底层创建的时候有一个代理缓存池,动态创建的时候会先去缓存中查找,有就直接返回,没有才创建,这也加大了程序的运行的效率。后者是程序运行前就已经存在的文件。
代理模式到这里就写完了,有很多作者写得比我好,也比我写的更高深,我仅仅是记录我自己现阶段理解的,仅此而已。如果各位读者能够阅读到这句话,希望能留下你们宝贵的意见,或者一些看法,让我能够学习改进一下,谢谢大家。
