代理模式-你不并知道我的存在

代理模式是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用。它的特征代理类与目标类有同样的接口,并且代理类与目标类之间通常存在关联关系。含有目标类的引用。以至于代理类能够控制目标对象,替它完成它的方法:预处理消息、过滤消息、把消息转发给目标类,以及事后处理消息等。

按照代理的创建时期,代理类可以分为两种:

静态代理:

UserManager接口:

public interface UserManager {

         public void addUser(String userId, String userName); //添加用户方法

         public String findUser(String userId); //删除用户方法

}

UserManagerImpl类:

public class UserManagerImpl implements UserManager { 

//用户添加

         public void addUser(String userId, String userName) {            

                   try {
                            System.out.println("用户ID" + userId);                   

                   }catch(Exception e) {

                            e.printStackTrace();                   

                            throw new RuntimeException();

                   }
         }        

//用户查询 

         public String findUser(String userId) {

                   System.out.println("用户ID" + userId);

                   return "张三";

         }

UserManagerImplProxy代理类:

      private UserManager userManager;  //含有目标类对象的引用         

         public UserManagerImplProxy(UserManager userManager) {

                   this.userManager = userManager;
         }
         public void addUser(String userId, String userName) {

                   try {
                            System.out.println("开始添加-->>添加用户ID" + userId);

                            userManager.addUser(userId, userName);

                            System.out.println("成功添加-->>addUser()");

                   }catch(Exception e) {

                            e.printStackTrace();

                            System.out.println("添加失败-->>addUser()");
                   }
         } 

public String findUser(String userId) {

                   return null;    //此处不实现,若是实现,其方式同add方法

         }

客户端调用:

public class Client {
         public static void main(String[] args) {
                   UserManager userManager = new UserManagerImplProxy(new UserManagerImpl());
                   userManager.addUser("0001", "张三");
         }

}

观察以上代码,可以发现每一个代理类只能为一个接口服务(public UserManagerImplProxy(UserManageruserManager))。这样一来需要建立大量的代理类。并且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样。例如,findUser中若是实现,将重复使用System.out.println("开始添加-->>添加用户ID"+
userId); System.out.println("成功添加-->>addUser()"); System.out.println("添加失败-->>addUser()");重复的代码出现多次对于开发人员来说是绝对不允许的,那么该怎么解决这个问题呢?最好的办法那就是通过一个代理类完成全部的代理功能,这就涉及到了动态代理。

动态代理:在程序运行时,运用反射机制动态创建而成。

代码示例:

UserManager接口:

public interface UserManager { 

         public void addUser(String userId, String userName);
         public String findUser(String userId);

}

真正实现类:

public class UserManagerImpl implements UserManager { 

         public void addUser(String userId, String userName) {            

                   try {
                            System.out.println("用户ID" + userId);          

                   }catch(Exception e) {
                            e.printStackTrace();
                            throw new RuntimeException();
                   }
         }

         public String findUser(String userId) {
                   System.out.println("用户ID" + userId);
                   return "张三";

         }

动态代理代理类:

public class LogHandler implements InvocationHandler {         

         private Object targetObject;

         //根据传过来的对象生成代理

         public Object newProxyInstance(Object targetObject) {

                   this.targetObject = targetObject;

                   return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),

                                targetObject.getClass().getInterfaces(), this);    //
         }         

         public Object invoke(Object proxy, Method method, Object[] args)

                            throws Throwable {

                   System.out.println("start-->>" + method.getName());

                   for (int i=0; i<args.length; i++) {

                            System.out.println(args[i]);
                   }

                   Object ret = null;
                   try {
                            //调用目标方法

                            ret = method.invoke(targetObject, args);

                            System.out.println("success-->>" + method.getName()); 

                   }catch(Exception e) {

                            e.printStackTrace();

                            System.out.println("error-->>" + method.getName());

                            throw e;
                   }
                   return ret;
         }
}

动态代理包含一个接口和一个类:

InvocationHandler接口:

Public static Object newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocatiocHandler h)

throws IllegalArgumentException

返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。

参数:

Loader:定义代理类的类加载器

Class<?>[]interfaces:得到全部的接口

InvocationHandlerh:得到InvocationHandler接口的子类实例

Proxy类:动态的声明出一个代理对象,为什么样生成出代理呢?这个类必须实现了接口才行。如果这个类没有实现接口,不能生成代理。说白了他就是根据这个接口在内存中建立出一个类。

客户端调用:

public class Client {

         public static void main(String[] args) {

                   LogHandler logHandler = new LogHandler();

                   UserManager userManager = (UserManager)logHandler.newProxyInstance(new UserManagerImpl());

                   userManager.addUser("001","猪猪");            

         }

}

总结:

动态代理相对于静态代理来说更加灵活了,为什么呢?例如重载和覆盖,重载属于静态的结构。当定义两个参数不一样的method方法时,我们在调用的时候,需要指定method方法的参数。也就是我们在编译的时候就指定好该调谁了。而覆盖的功能更强,因为它的方法调用不是静态的时候进行绑定,也不是说我写代码编译的时候就指定好我应该调谁。而是在运行的时候决定它是什么类型就调谁。

正常情况下,我们需要创建很多的代理类,如果我还有其他的manager也需要完成这些功能,那么她还需要创建代理类,来完成。动态代理则不用,因为这个proxySubject这个类不需要自己创建,他在内存中创建。所以你压根就不知道代理类的存在,当然代理类的个数,也不需要你关心。

时间: 2024-11-08 22:18:19

代理模式-你不并知道我的存在的相关文章

Spring框架_代理模式(静态代理,动态代理,cglib代理)

共性问题: 1. 服务器启动报错,什么原因? * jar包缺少.jar包冲突 1) 先检查项目中是否缺少jar包引用 2) 服务器: 检查jar包有没有发布到服务器下:                                      用户库jar包,需要手动发布到tomcat. (每次新建项目) 3) 重新发布项目 * 配置文件错误 (web.xml / struts.xml /bean.xml /hibernate.xml / *.hbm.xml) 明确的提示 * 端口占用 * we

拦截器的设计思想——代理模式

代理模式:静态代理和动态代理 1.代理类和被代理类必须实现同一个借口 2.代理类和别代理类有一种关联关系 静态代理: 例如实现一个日志: //定义一个接口 public interface UserDao{ public void delete(); } //定义一个实现类 public class UserDaoImpl implements UserDao{ public void delete(){ System.out.pritln("成功删除"); } } //定义一个代理类

Java设计模式——代理模式

前言: 上一篇说到了策略模式.单类图上来说,它和本篇要说的代理模式还真是有些像似.都需要一个公共的接口,还有一些实现类.代理类(包装类)封装了一个接口对象,提供客户端调用.这些都很类似.不过,有一个细节需要我们注意一下,那就是这里的代理类也需要去继承这里的公共接口.而在策略模式中,包装类则不需要这么做. 概述: 代理模式就是定义一个原对象的代理对象,来帮助原对象和系统之外的业务作沟通.也就是说,如果我们不能直接或是不愿直接去使用原对象,那么我们就可以使用创建一个原对象的代理来进行操作. 本文链接

代理模式(Proxy)

代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式一般涉及到的角色有 抽象角色:声明真实对象和代理对象的共工接口 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象.同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装. 真实角色:代理角色所代表的真实对

深刻理解代理模式在java中如何优化系统性能

最近参与实习公司的项目迭代,项目中需要实现系统的快速响应和大量数据处理.在不断的学习中获得一点儿心得,先记录下来.慢慢的修改! 关于代理模式的知识和简单应用之前的学习笔记中已经有记录了,可以复习一下.这里主要记录如何使用代理模式来实现延迟加载,进而提升系统系能和反应速度. 使用代理模式实现延迟加载的一个简单实例: 需求:项目中对系统的启动速度做了一定的要求 我们在系统首次加载时,因为不需要实际的数据来构造显示界面,这就为我们实现系统首次加载的快速响应提供了可能.在常规模式下,我们一般会在系统启动

使用反射机制调用属性和私有成员与代理模式的介绍

使用反射机制调用属性: 通过反射机制可以获得类的属性,获得到的属性同样的可以进行赋值.得值操作,调用getField方法并传递属性的名称可以获得[学Java,到凯哥学堂kaige123.com]指定的属性,调用getFields方法则可以获得全部属性,但是这种方式不能获得私有属性: 代码示例: Student类示例: 运行结果: 从运行结果可以看出只拿出了公开的属性,私有的属性拿不到. 使用反射机制调用私有成员: 1.调用私有属性 在反射机制里调用私有属性需要通过getDeclaredField

动态代理模式

动态代理模式简介: 动态代理能够自动监听代理对象的方法,并且能够自动生成代理类的代码,这样就不需要我们自己去重写代理对象里的方法了,这样解决了代理类代码因业务庞大而庞大的问题,因为动态代理模式会在代码运行时根据代码来在内存中动态生成一个代理类自动重写代理对象[学Java,到凯哥学堂kaige123.com]的方法,然后这个动态代理类再调用处理类里的代码,处理类再调用到实际方法上去.而且我们可以选择性的监听代理对象的方法,有些不需监听的方法就可以在处理类中过滤掉.所以动态代理的优势就在于可以自动的

设计模式(十四):代理模式

一.概述 代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问.其实就是代理就是做到类似转发的功能,针对不同代理,转发的具体实现不同. 二.解决问题 从原理知道他就是控制客户对一个对象的访问,它跟现实中的中介代理类似,只是作为代表做一些受理工作,真正执行的并不是它自己.比如买火车票,外面有很多火车票代理点,我们直接去代理点买票就好而不用跑到火车票买了(暂时不考虑网购哈). 三.结构类图 四.应用实例 在这个例子中,主要讲解远程代理,它可以作为另一个JVM上的本地代表.客户端调用代理的方

设计模式之代理模式

代理模式(Proxy)为其他对象提供一种代理以控制对这个对象的访问.使用场合,第一,远程代理,也就是为一个对象在不同的地址空间提供局部代表.这样可以隐藏一个对象存在于不同地址空间的事实:第二,虚拟代理,是根据需要创建开销很大的对象.通过它来存在实例化需要很长时间的真实对象:第三,安全代理,用来控制真实对象访问时的权限:第四,智能指引,是指当调用真实的对象时,代理处理另外一些事情.代理模式与外观模式有点像,但外观模式中外观与实体不一定具备相同的接口,两者都在一定程度上隐藏了系统的复杂性. 代理模式

23种设计模式--代理模式-Proxy

一.代理模式的介绍       代理模式我们脑袋里出现第一个词语就是代购,其实就是这样通过一个中间层这个中间成是属于什么都干什么都买得,俗称"百晓生",在平时得开发中我们经常会听到什么远程代理,虚拟代理等等这一些都是代理模式得具体例子,来个官方定义就是给某一个对象提供一个代理,并由代理对象控制对原对象的引用:下面我们用代购的例子来说明一下这个情况:你想买一台iphone,国行有点贵,然后拜托海外的朋友买一台给你带回来,就是这样的一个例子,首先我们先将买东西这个主题抽象出来,然后再把真实