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

 

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

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

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

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

package com.safly;
public interface MyInterface {
    void myBuyTicket();
}

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

package com.safly;
public class My implements MyInterface{

    @Override
    public void myBuyTicket() {
        System.out.println("我买票");
    }
}

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

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();
    }
}

看看主界面把

package com.safly;

public class MyMainUI {
    public static void main(String[] args) {

        Station station = new Station(new My());

        station.stationBuyTicket();
    }
}

输出如下:

station buyTicket
我买票
  • 以上就是一个静态代理类,自己的买票方法,车站的一个方法,感觉2个方法名字不同,这样感觉不好,我们能不能同样实现一个相同的接口呢?就是同一个接口,这样看起来,效果更好,意思更明确,那我们就来改下把
package com.safly;
public interface MyInterface {
    void myBuyTicket();
}
package com.safly;

public class My implements MyInterface{

    @Override
    public void myBuyTicket() {
        System.out.println("我买票");
    }
}
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();

    }
}
package com.safly;

public class MyMainUI {
    public static void main(String[] args) {
        Station station = new Station(new My());
        station.myBuyTicket();
    }
}

输出log如下:

station buyTicket
我买票
  •  

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

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

在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;  
    }  

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

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

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

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

loader:  一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载

interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了

h:  一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
package com.safly;
public interface MyInterface {
    void myBuyTicket();
}
package com.safly;
public class My implements MyInterface{
    @Override
    public void myBuyTicket() {
        System.out.println("我买票");
    }
}
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;
    }
}
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();
    }
}

Log日志输出如下:

satrt-->>
我买票
success-->>

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

My

package com.safly;
public class My implements MyInterface{
    @Override
    public void myBuyTicket(int money) {
        System.out.println("我买票"+money);
    }
}

MyInterface

package com.safly;
public interface MyInterface {
    void myBuyTicket(int money);
}

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;

    }
}

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);

    }
}

输出如下:

我买票100
我买票200
posted @ 2017-02-24 08:51  vegatate  阅读(111)  评论(0编辑  收藏  举报