Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问。

  所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后),进行某些特别的处理。

  代理模式的结构

  代理模式的角色与职责

   1、subject(抽象主题角色):真实主题与代理主题的共同接口或抽象类。

   2、RealSubject(真实主题角色):定义了代理角色所代表的真实对象。

   3、Proxy(代理主题角色):含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真是主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。

  举个例子说明一下代理模式

  比如说买书,网上有很多专门卖书的网站,我们从这些商城买书,但是书不是这些商城印的,他们只负责卖,书是出版社印的,所以说到底,我们其实还是从出版社买书,网上书城只是出版社的代理,所以出版社是被代理对象,书城是代理对象。

  所以,根据角色与职责划分,subject(抽象主题角色)就是卖书,卖书是书城与出版社的共同功能,RealSubject(真实主题角色)就是出版社,它的功能就是卖书,但不直接卖给用户,而是被书城代理,通过代理来卖,Proxy(代理主题角色)就是书城,根据概念发现,代理对象在代理的过程中不仅仅只有被代理对象的功能,他还会执行某些他自己的操作,这个意思是,比如,书城会推出优惠券与打折活动。在卖书的基础上,增加许多功能来吸引消费者。

  接下来,我们用代码实现刚才的例子:

  代理模式分为两种类型:(1)静态代理(2)动态代理

  (1)静态代理

  (静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类)

  首先,创建subject,一个接口,是代理对象与被代理对象的共同接口

  书城与出版社都有卖书的功能

 public interface Subject {
public void sailBook();
}

  然后,创建RealSubject,被代理对象,也就是出版社

 public class RealSubject implements Subject {

     @Override
public void sailBook() {
System.out.println("卖书");
} }

  然后,创建代理对象,也就是书城

 public class ProxySubject implements Subject{
//代理对象含有对真实主题角色的引用
private Subject subject; public ProxySubject(Subject subject){
this.subject = subject;
} @Override
public void sailBook() {
dazhe();
this.subject.sailBook();
give();
} //代理角色通常在将客户端调用传递给真是主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。
public void dazhe(){
System.out.println("打折");
} public void give(){
System.out.println("赠送代金券");
} }

  最后,创建客户端,也就是用户

  首先如果,不使用代理直接从出版社买

 public class MainClass {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
realSubject.sailBook();
}
}

  结果如下:仅仅是卖书

  而如果我们通过代理也就是书城来买

 public class MainClass {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
Subject proxySubject = new ProxySubject(realSubject);
proxySubject.sailBook();
}
}

  结果变成了这样,作为用户,我们享受了更多的优惠,所以我们当然更愿意通过代理来买

  

  静态代理总结:
  1、可以做到在不修改目标对象的功能前提下,对目标功能扩展.
  2、缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.

  如何解决静态代理中的缺点呢?答案是可以使用动态代理方式

  (2)动态代理

  动态代理有以下特点:

  1.代理对象,不需要实现接口

  2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)

  3.动态代理也叫做:JDK代理,接口代理

  代理代理,Subject与RealSubject不变

    而使用动态代理,首先要创建代理实例的调用处理程序,通过这个程序来执行代理对象特有的方法

  创建MyHandler实现InvocationHandler(是代理实例的调用处理程序 实现的接口)这个接口,并覆盖invoke(Object proxy, Method method, Object[] args)这个方法。

 Object invoke(Object proxy, Method method, Object[] args)
          在代理实例上处理方法调用并返回结果。
 1 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class MyHandler implements InvocationHandler{
//这里也需要传入被代理对象
private Subject subject; public MyHandler(Subject subject){
this.subject = subject;
} //这个方法中就是代理对象要执行的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
dazhe();
//执行被代理对象中的方法
Object result = method.invoke(subject, args);
give();
return result;
} public void dazhe() {
System.out.println("打折");
} public void give() {
System.out.println("赠送代金券");
}
}

  最后,写客户端,客户端中需要动态创建代理对象,要使用Proxy类中的newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
          返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。

  参数:

  loader - 定义代理类的类加载器
  interfaces - 代理类要实现的接口列表
  h - 指派方法调用的调用处理程序
  返回:
  一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
  抛出:
  IllegalArgumentException - 如果违反传递到 getProxyClass 的参数上的任何限制
  NullPointerException - 如果 interfaces 数组参数或其任何元素为 null,或如果调用处理程序 hnull

  所以三个参数,第一个是RealSubject的类加载器,第二个是被代理类要实现的接口列表,第三个就是处理程序也就是MyHandler

 public class MainClass {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
MyHandler myHandler = new MyHandler(realSubject);
//创建代理对象实例
Subject proxySubject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(), realSubject.getClass().getInterfaces(), myHandler);
proxySubject.sailBook();
}
}

  结果是相同的

   总结:代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理

java设计模式-----11、代理模式的更多相关文章

  1. Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景

    我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...

  2. java设计模式6——代理模式

    java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...

  3. 夜话JAVA设计模式之代理模式(Proxy)

    代理模式定义:为另一个对象提供一个替身或者占位符以控制对这个对象的访问.---<Head First 设计模式> 代理模式换句话说就是给某一个对象创建一个代理对象,由这个代理对象控制对原对 ...

  4. Java设计模式:代理模式(转)

    代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一 ...

  5. Java 设计模式_代理模式(2016-08-19)

    概念: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 就是一个人或者机构代表另一个人或者机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...

  6. JAVA设计模式:代理模式&& 装饰模式区别

    在前面学习了代理模式和装饰模式后,发现对两者之间有时候会混淆,因此对两者进行了区别和理解: 装饰模式你可以这样理解,就像糖一样,卖的时候商家大多要在外面包一层糖纸,其实原本还是糖. public in ...

  7. Java设计模式:代理模式(二)

    承接上文 三.计数代理 计数代理的应用场景是:当客户程序需要在调用服务提供者对象的方法之前或之后执行日志或者计数等额外功能时,就可以用到技术代理模式.计数代理模式并不是把额外操作的代码直接添加到原服务 ...

  8. java设计模式之代理模式 ,以及和java 回调机制的区别

    java 代理模式就是: 将自己要做的事交给别人去做(这个别人就是代理者,自己就是被代理者),为什么自己能做的要交给别人去做了?假如一个小学生小明,现在要写作业,但是又想玩游戏,他更想玩游戏,并且不想 ...

  9. Java设计模式之代理模式(Proxy)

    前言: 最近在研究Retrofit开源框架的时候,其主要核心代码是通过注解标示参数,动态代理模式实现具体接口,反射机制进行参数解析,最终实现发送请求.其实之前在学习Xutils源码的时候,Xutils ...

  10. Head First 设计模式 --11 代理模式

    代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问. 代码: interface Boss { public void meeting(); } class BossImp implem ...

随机推荐

  1. 一个shell脚本给客户使用服务器生成一个序列号

    #!/bin/bash interface=`ls /sys/class/net|grep en|awk 'NR==1{print}'` if [ ! -e /etc/adserver/.seq.in ...

  2. Linux终端下 dstat 监控工具

    dstat 是一个可以取代vmstat,iostat,netstat和ifstat这些命令的多功能产品.dstat克服了这些命令的局限并增加了一些另外的功能,增加了监控项,也变得更灵活了.dstat可 ...

  3. H-ui.admin v2.3后台模版!

    一个很好的 后台开发模板 演示地址 http://demo.h-ui.net/H-ui.admin/3.1/index.html 下载地址 http://downs.h-ui.net/h-ui/H-u ...

  4. 利用ajax获取网页表单数据,并存储到数据库之一(使用JDBC)

    所谓JDBC就是利用java与数据库相连接的技术,从数据库获取既有的信息或者把网页上的信息存储到数据库. 这里简单的介绍公司的一个小项目中的一部分,由于代码较多,所以用图片形式进行展示.源码请查看源码 ...

  5. HDU 3001(状态压缩dp)

    状态压缩dp的第一题! 题意:Mr ACMer想要进行一次旅行,他决定访问n座城市.Mr ACMer 可以从任意城市出发,必须访问所有的城市至少一次,并且任何一个城市访问的次数不能超过2次.n座城市间 ...

  6. ARM平台的虚拟化介绍

    本篇博文主要介绍虚拟化的基本思想以及在arm平台如何做虚拟化,arm提供的硬件feature等等. 虚拟化技术简介 虚拟化技术 虚拟化是一个概念,单从这个概念的角度来看,只要是用某一种物品去模拟另一种 ...

  7. 设置TCP_USER_TIMEOUT参数来判断tcp连接是否断开

    [TOC] 1. bug描述 前段时间遇到这样的一个问题,openstack一个控制节点宕机后,在宕机后一段时间内创建的虚拟机,一直卡在创建中的状态.有的甚至要等到16分钟之后虚拟机才会切换到下一个状 ...

  8. HTTP状态码作用

    文章目录 状态码分类 常见的状态码 1xx消息 2xx成功 3xx重定向 4xx客户端错误 5xx服务器错误 HTTP状态码的作用是:web服务器用来告诉客户端,发生了什么事. 状态码位于HTTP R ...

  9. javascript类型判断方法

    判断javascript中的类型,共有四种常用的方法 var a=6; var b="str"; var c=true; var arr=[]; typeof 用于基本类型的判断 ...

  10. MAVEN自动发布更新本地和远程仓库

    1.本地仓库 的更新 mvn  clean package install  2.远程 仓库 的更新 mvn clean package deploy 2.1工程文件pom.xml的设置 <bu ...