博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【java设计模式】之 代理(Proxy)模式
阅读量:5990 次
发布时间:2019-06-20

本文共 3419 字,大约阅读时间需要 11 分钟。

代理模式的核心作用就是通过代理,控制对对象的访问。这跟实际中是一样的,比如说明星都有经纪人,这就是一个代理,比如有人要找某明星拍戏,那么首先处理这事的是他的经纪人,虽然拍戏需要自己拍,但是拍戏前后的一些必须要做的事等等,都由这个经纪人来处理。 

  在程序中也是如此,通过代理,可以详细控制访问某个或者某类对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。这也是AOP的实现原理。 
  那么代理模式的核心角色该如何设计呢?

设计思路:定义一个抽象角色,让代理角色和真实角色分别去实现它。 

1. 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用它只关注真正的业务逻辑,比如拍戏。 
2. 代理角色:实现抽象角色,是真实角色的代理,通过真是角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作,比如谈合同,布置场地等等。

  下面来具体实现这个代理模式,代理模式分为静态代理和动态代理。静态代理是我们自己创建一个代理类,而动态代理是程序自动帮我们生成一个代理,我们就不用管了。

 

1. 静态代理

 

根据上面的实现步骤,首先来写一个抽象角色:

 

/** * @Description 接口类 * @author shanheyongmu * */public interface Star {    public void confer(); //面谈    public void sing(); //唱歌    public void collectMoney(); //收钱}

 

这个抽象类中有三个方法,现在分别让真实角色和代理角色来实现该抽象类:

/** * @Description 真实对象 * @author shanheyongmu * */public class RealStar implements Star {    @Override    public void confer() {        System.out.println("RealStar.confer()");    }    @Override    public void sing() {        System.out.println("RealStar(周杰伦).sing()");    }    @Override    public void collectMoney() {        System.out.println("RealStar.collectMoney()");    }}

唱歌部分,注明一下周杰伦,等会好区分。下面再来看下代理类。

/** * @Description 代理类 * @author shanheyongmu * */public class ProxyStar implements Star {    private Star star;    public ProxyStar(Star star) { //到时候传进来真实的star        super();        this.star = star;    }    @Override    public void confer() {        System.out.println("ProxyStar.confer()");    }    @Override    public void sing() {        //其他事都能干,唯一不能干的就是唱歌,唱歌还是得要周杰伦本人来唱        star.sing(); //让他本人来唱    }    @Override    public void collectMoney() {        System.out.println("ProxyStar.collectMoney()");    }}

在代理类中,可以看到,维护了一个Star对象,通过构造方法传进来一个真实的Star对象给其赋值,然后在唱歌这个方法里,使用真实对象来唱歌。所以说面谈、收钱都是由代理对象来实现的,唱歌是代理对象让真实对象来做。 

下面写个客户端的测试用例:

 

public class Client {    public static void main(String[] args) {        Star real = new RealStar();        Star proxy = new ProxyStar(real);        proxy.confer();        proxy.sing();        proxy.collectMoney();    }}

 

输出结果:

ProxyStar.confer() 

RealStar(周杰伦).sing() 
ProxyStar.collectMoney()

可以看出,客户端只跟代理对象打交道,代理对象把能做的都做了,比如面谈和收钱,唱歌呢,是调用真实对象去唱。

2. 动态代理

  动态代理比静态代理使用的更广泛,动态代理在本质上,代理类不用我们来管,我们完全交给工具去生成代理类。Star接口和RealStar实现类还是和上面的一样,下面来定义一下代理类,使用动态代理需要实现InvocationHandler接口,并覆写里面的invoke方法,如下:

/** * @Description 动态代理类 * @author shanheyongmu * */public class StarHandler implements InvocationHandler {    Star realStar;    public StarHandler(Star realStar) {        super();        this.realStar = realStar;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        Object object = null;        // 在代理真实对象前,我们可以做些自己的操作        System.out.println("面谈");        if(method.getName().equals("sing")) {            object = method.invoke(realStar, args);        }        // 在代理真是对象后,我们可以做些自己的操作        System.out.println("收钱");        return object;    }}

可以看出,思路和静态代理是一样的,先通过构造方法把真正的对象传进来,然后执行代理的部分是invoke方法中,在该方法中,我们进行一次判断,只有当需要唱歌的时候,我就调用刚刚传进来的真实对象来唱,其他事情由代理代替真实对象来做,这里只用控制台输出来模拟一下。 

  最后来写个客户端测试一下:

public class Client {    public static void main(String[] args) {        Star realStar = new RealStar();        StarHandler handler = new StarHandler(realStar);        //创建代理类        Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Star.class}, handler);               proxy.sing();    }}

看下控制台输出:

面谈 

RealStar(周杰伦).sing() 
收钱

  由此可见,使用代理可以在执行某个逻辑的前后加上新的逻辑,这是很好的功能,实际中的AOP用的就是这种技术。 

 

 

转载地址:http://dxjlx.baihongyu.com/

你可能感兴趣的文章
国内PaaS概述和EEPlat定位
查看>>
Android Fragement学习笔记(三)----PreferenceFragment使用
查看>>
简单介绍一下线程池和数据库连接池的原理
查看>>
Nim教程【九】
查看>>
Non Lasting Storage File System、procfs、sysfs
查看>>
Android复制WIN8点击下沉倾斜系统瓷砖效果
查看>>
Bootstrap系列 -- 7. 列表排版方式
查看>>
libSVM 参数选择
查看>>
三石推荐!把 Bootstrap 小清新带回家!
查看>>
Android ContentObserver
查看>>
Linux性能分析top iostat vmstat free
查看>>
Python 2.7.9 Demo - 005.字符串判空
查看>>
ACM-简单的主题Ignatius and the Princess II——hdu1027
查看>>
C#流水号生成汇总(四)
查看>>
深入学习微框架:Spring Boot(转)
查看>>
codeforces Gym 100187B B. A Lot of Joy
查看>>
写作技巧--Simile明喻
查看>>
决策树0-基本模型
查看>>
【linux高级程序设计】(第十三章)Linux Socket网络编程基础 2
查看>>
串行卧重建10:小设计,而不是大布局
查看>>