java设计模式----代理模式

来源:互联网 发布:js offsettop 编辑:程序博客网 时间:2024/05/29 12:32


什么是代理模式? 
代理模式的定义:对其他对象提供一种代理以控制对这个对象的访问—来自百度搜索

让我们用一种通俗的语言来理解下代理模式 
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。 
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。 
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

我还是举个例子来说明下,比如我去火车站买票这个例子 
我就是被代理类,火车站就是代理类,我们需要明白一点,就是真正花钱买票的是我本人,而不是火车站,所以最后调用买票的方法是执行的被代理的方法,这个买票的方法,肯定是属于被代理类的,一句话就是被代理类有一个方法或者是接口,用来实现买票的功能 
如果直接调用自己的方法去实现购票,谈何代理?所以接下来就分析下代理类-车站,我们调用车站的某个方法,其实本质上就是调用了我自己买票的方法,这里很关键,车站类里面肯定有一个我这个对象,为什么呢?因为车站调用某个方法是调用的我这个对象的方法,没有我这个对象,谈何调用?另外车站类里面,在随便定义一个方法,车站的方法里面在让我去调用自己的买票方法即可

来看下代码咯: 
首先看下我这个人的一个接口方法,就是我买票的未实现的方法

package com.safly;public interface MyInterface {    void myBuyTicket();}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

在来看看我这个本类,实现方法即可,我就输出一句话即可

package com.safly;public class My implements MyInterface{    @Override    public void myBuyTicket() {        System.out.println("我买票");    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

接下来就看看代理类了,里面持有我一个引用,然后有随便一个方法,方法里面在调用我自己的方法即可

package com.safly;public class Station {    public My my;    public Station(My my) {        super();        this.my = my;    }    public void stationBuyTicket(){        System.out.println("station buyTicket");        my.myBuyTicket();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

看看主界面把

package com.safly;public class MyMainUI {    public static void main(String[] args) {        Station station = new Station(new My());        station.stationBuyTicket();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

输出如下:

station buyTicket我买票
  • 1
  • 2
  • 1
  • 2

以上就是一个静态代理类,自己的买票方法,车站的一个方法,感觉2个方法名字不同,这样感觉不好,我们能不能同样实现一个相同的接口呢?就是同一个接口,这样看起来,效果更好,意思更明确,那我们就来改下把

package com.safly;public interface MyInterface {    void myBuyTicket();}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
package com.safly;public class My implements MyInterface{    @Override    public void myBuyTicket() {        System.out.println("我买票");    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
package com.safly;public class Station implements MyInterface{    public My my;    public Station(My my) {        super();        this.my = my;    }    @Override    public void myBuyTicket() {        System.out.println("station buyTicket");        my.myBuyTicket();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
package com.safly;public class MyMainUI {    public static void main(String[] args) {        Station station = new Station(new My());        station.myBuyTicket();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出log如下:

station buyTicket我买票
  • 1
  • 2
  • 1
  • 2

以上就是静态代理,我们在来看下动态代理?

静态代理相对应动态代理有什么缺点呢? 
如果上楼的例子里面,车站代理了我本人买票,如果在来一个人,他也要买票呢?车站需要在买票接口,去判断买票的人是谁吧?还得持有另外一个人的引用,这样设计起来,代码就会很臃肿,所以动态代理就为了解决这个问题,产生了。 
(当然我是自己这样理解的,你还可以搜搜百度)

在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 类的支持 
,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用

    //Object proxy:被代理的对象      //Method method:要调用的方法      //Object[] args:方法调用时所需要参数      public interface InvocationHandler {          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;      }  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

代理类是通过Proxy.newProxyInstance得到一个动态的代理对象

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,  InvocationHandler h)  throws IllegalArgumentException
  • 1
  • 1

以上3个参数的意思如下:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentExceptionloader:  一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了h:  一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
package com.safly;public interface MyInterface {    void myBuyTicket();}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
package com.safly;public class My implements MyInterface{    @Override    public void myBuyTicket() {        System.out.println("我买票");    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
package com.safly;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Station implements InvocationHandler {    /**     * 被代理对象targetObject通过参数传递进来,我们通过targetObject.getClass().getClassLoader()     * 获取ClassLoader对象,然后通过targetObject.getClass().getInterfaces()获取它实现的所有接口,     * 然后将targetObject包装到实现了InvocationHandler接口的LogHandler对象中     * 。通过newProxyInstance函数我们就获得了一个动态代理对象。     */    private Object targetObject;    public Object newProxyInstance(Object targetObject) {        this.targetObject = targetObject;        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),                targetObject.getClass().getInterfaces(), this);    }    @Override    public Object invoke(Object arg0, Method method, Object[] arg2)            throws Throwable {        Object ret = null;        try {            System.out.println("satrt-->>");            // 调用目标方法            ret = method.invoke(targetObject, arg2);            System.out.println("success-->>");        } catch (Exception e) {            e.printStackTrace();            System.out.println("error-->>");            throw e;        }        return ret;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
package com.safly;public class MyMainUI {    public static void main(String[] args) {        Station station = new Station();        MyInterface myInterface = (MyInterface) station                .newProxyInstance(new My());        myInterface.myBuyTicket();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Log日志输出如下:

satrt-->>我买票success-->>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

接下来,我们就修改修改参数等操作

My

package com.safly;public class My implements MyInterface{    @Override    public void myBuyTicket(int money) {        System.out.println("我买票"+money);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

MyInterface

package com.safly;public interface MyInterface {    void myBuyTicket(int money);}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

Station

package com.safly;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Station implements InvocationHandler {    private Object targetObject;    Station(Object targetObject) {        this.targetObject = targetObject;    }    @Override    public Object invoke(Object arg0, Method method, Object[] arg2)            throws Throwable {        Object ret = null;        if ("myBuyTicket".equals(method.getName())) {            // 这里是代理Shopping接口的对象            // 先黑点钱(修改输入参数)            Integer money = (Integer) arg2[0];            Integer finalMoney = (Integer) (money * 2);            ret = method.invoke(targetObject, finalMoney);            // 帮忙买东西        }        return ret;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

MyMainUI

package com.safly;import java.lang.reflect.Proxy;public class MyMainUI {    public static void main(String[] args) {        MyInterface my = new My();        my.myBuyTicket(100);        my = (MyInterface) Proxy.newProxyInstance(my.getClass()                .getClassLoader(), my.getClass().getInterfaces(), new Station(                my));        my.myBuyTicket(100);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

输出如下:

我买票100我买票200
0 0
原创粉丝点击