java设计模式之代理模式

代理模式定义:是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网络连接、存储器中的对象、文件或其它昂贵或无法复制的资源。

举一个简单的例子:说现在有一家公司要拍古装电视剧有剧本,想要有流量就需要有明星参演,于是想要邀请胡歌参演,但是不能直接去找胡歌本人所以只能去找胡歌的经纪人谈关于签约参演的事情

代理模式角色:

  • 抽象对象角色 (明星)
  • 具体对象角色(胡歌)
  • 代理对象角色(胡歌经纪人)

1、抽象对象角色创建

package com.weather.spring.cloud.initializrstart.design.mode.proxy.staticproxy;

import java.util.Date;

/**
 * @program: msa-weather-master
 * @description: This is  all star people service
 * @author: W.HL
 * @create: 2019-04-04 10:03
 **/

public interface Star
{
    /**
     *  star person name
     */
    void starName();

    /**
     * person Performance
     */
    void showTime(Date time);
}

2、具体对象角色创建

package com.weather.spring.cloud.initializrstart.design.mode.proxy.staticproxy;


import java.text.DateFormat;
import java.util.Date;

/**
 * @program: msa-weather-master
 * @description: Thi is HuGe class
 * @author: W.HL
 * @create: 2019-04-04 10:04
 **/

public class HuGe implements Star
{

    @Override
    public void starName()
    {
        System.out.println("大家好! 我是胡歌");
    }

    /**
     * person Performance
     */
    @Override
    public void showTime(Date time)
    {
        System.out.println("最近演出时间为:"+DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).format(time));
    }
}

3、代理对象角色创建

package com.weather.spring.cloud.initializrstart.design.mode.proxy.staticproxy;

import java.io.PrintStream;
import java.util.Date;

/**
 * @program: msa-weather-master
 * @description: Thi is agent person for star people
 * @author: W.HL
 * @create: 2019-04-04 10:11
 **/

public class AgentPerson implements Star
{
    private Star star;

    public AgentPerson(Star star)
    {
        this.star = star;
    }
    /**
     * star person name
     */
    @Override
    public void starName()
    {
        star.starName();
    }
    /**
     * person Performance
     *
     * @param time
     */
    @Override
    public void showTime(Date time)
    {
        star.showTime(time);
    }

    public static void main(String[] args)
    {
        /*get the star*/
        Star agentPerson = new AgentPerson(new HuGe());
        agentPerson.starName();
        agentPerson.showTime(new Date());
    }
}

执行结果:

java设计模式之代理模式_第1张图片

此为静态代理模式

缺点:

1、如果代理对象里面的方法少的时候可以,但是如果里面很多方法呢?则都需要在代理对象中一一实现,造成了代码的冗余

2、如果这时候这个经纪人同时也是唐嫣的经纪人则代理人中的部分方法不能重复利用

于是对代理进行了升级变为动态代理,只改变代理本身其他保持不变

package com.weather.spring.cloud.initializrstart.design.mode.proxy.dynamicproxy;



import com.weather.spring.cloud.initializrstart.design.mode.proxy.staticproxy.HuGe;
import com.weather.spring.cloud.initializrstart.design.mode.proxy.staticproxy.Star;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Date;

/**
 * @program: msa-weather-master
 * @description: This is star dynamic proxy
 * @author: W.HL
 * @create: 2019-04-04 10:26
 **/

public class AgentDynamicProxy implements InvocationHandler
{
    private Object object;

    public AgentDynamicProxy(Object object)
    {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        return method.invoke(object,args);
    }

    public static void main(String[] args)
    {
        /*获取代理对象*/
        InvocationHandler invocationHandler = new AgentDynamicProxy(new HuGe());

        /*创建动态代理对象*/
       Star star = (Star) Proxy.newProxyInstance(new HuGe().getClass().getClassLoader(),new Class[]{Star.class},invocationHandler);
       star.starName();
       star.showTime(new Date());

    }
}

InvocationHandler源码解析

通过实现java中提供的InvocationHandler接口然后使用反射机制来调用相应具体代理对象的方法

/**
 * {@code InvocationHandler} is the interface implemented by
 * the invocation handler of a proxy instance.
 *
 * 

Each proxy instance has an associated invocation handler. * When a method is invoked on a proxy instance, the method * invocation is encoded and dispatched to the {@code invoke} * method of its invocation handler. * * @author Peter Jones * @see Proxy * @since 1.3 */ public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }

解析:每个代理实例都有一个关联的调用处理程序。当在代理实例上调用方法时,则会被分配到其相应的实现的invoke中调用处理程序,所以如果想要调用其方法则需要在具体实现的invoke方法中通过传来的对象通过invoke找到其真正的方法

InvocationHandler源码中invoke方法解析

当执行到star.starName();继续执行的时候进入到invoke中,可以看到具体的代理对象以及具体的代理方法java设计模式之代理模式_第2张图片

newProxyInstance方法源码解析

newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
     * @param   loader the class loader to define the proxy class
     * @param   interfaces the list of interfaces for the proxy class
     *          to implement
     * @param   h the invocation handler to dispatch method invocations to
     * @return  a proxy instance with the specified invocation handler of a
     *          proxy class that is defined by the specified class loader
     *          and that implements the specified interfaces
     * @throws  IllegalArgumentException if any of the restrictions on the
  • ClassLoader loader: 类加载器中的AppClassLoader,此处使用具体代理对象的类加载器。
  • Class[] interfaces:抽象对象角色 (明星)所有代理对象和具体代理对象(胡歌)的接口。
  • InvocationHandler h :当前的InvocationHandler接口实现的具体对象(代理对象)。

动态代理通过反射机制很好的实现代理可以重复调用重复使用,可以在不修改原来代码的基础上添加新特性比如新增话剧、演唱会、舞蹈等

你可能感兴趣的:(java)