代理模式

依照java万物皆对象的思想,代理模式自然也可以往现实中作映射。那么代理模式是什么呢?其实就是我们身边常见的——中介。

当我们想要买会跑,会飞的车子时。我们可以自己去到各个4s店去看车,也可以把我们的要求委托给中介,由中介把合适的车子卖给我们。

代理模式定义:为其他它对象提供代理,对原对象的访问进行控制,并可以去除或增加一些服务。

代理模式结构:

  interface :抽象角色,一个接口,由原对象和代理对象共同继承。

  primaryModel: 原对象角色,原对象,一个实现了接口的类。

  proxy: 代理角色,代理对象,内部对原对象进行引用,提供与原对象相对的接口,以完全代替原对象,并能对原对象的功能进行拓展。

静态代理:由开发者定义,程序运行前就已编译。

  优点:扩展原对象功能,不入侵源代码。

  缺点:在给不同的对象拓展相对的代码逻辑时,也要分别创建代理类,导致需要编写重复的功能代码。

  1.由聚合实现:  

/**
 *  @Author SZF
 *
 * @Date 2018-08-09
 *
 */
    //抽象接口
    public interface WantCar {
         void canRun();
         void canFly();
    }
    //原类
    public class PrimaryCar implements WantCar {
        public void canRun() {
            System.out.println("I can run!");
        }
        public void canFly() {
            System.out.println("I can fly!");
        }
    }
    //聚合代理
    public class ProxyCar extends PrimaryCar{
        private PrimaryCar pcar;
        public ProxyCar (PrimaryCar pcar) {
            super();
            this.pcar=pcar;
        }
        public void canRun() {
            System.out.println("I can run!");
            System.out.println("I can run at Moon!");//拓展
        }
        public void canFly() {
            System.out.println("I can fly!");
            System.out.println("I can fly at Mars");//拓展
        }
    }
    //使用
    PrimaryCar pcar=new PrimaryCar();
    WantCar wcar=new ProxyCar(pcar);
    wcar.canRun();
    wcar.canFly();


  2.由继承实现:

/**
 *  @Author SZF
 *
 * @Date 2018-08-09
 *
 */
    //抽象接口
    public interface WantCar() {
         void canRun();
         void canFly();
    }
    //原类
    public class PrimaryCar implements PrimaryCar {
        public void canRun() {
            System.out.println("I can run!");
        }
        public void canFly() {
            System.out.println("I can fly!");
        }
    }
    //继承代理
    public class ProxyCar implements WantCar{
        @Override
        public void canRun() {
            super.canRun();
            System.out.println("I can run at Moon!");//拓展
        }
        public void canFly() {
            super.canFly();
            System.out.println("I can fly at Mars");//拓展
        }
    }
    //使用
    ProxyCar pcar=new ProxyCar();
    pcar.canRun();
    pcar.canFly();

 以上两种实现方式相比较,继承式不够灵活。举个栗子,原类中有1,2两种方法,每种方法程序执行先后顺序导致的结果不同。

此时继承式写法就需要编写两个不同的代理类(1,2)(2,1),相比之下,聚合式只需要改变方法的调用顺序就行了。

 

动态代理:于程序运行期自动创建,为了解决静态代理的缺点而存在。

想要实现动态代理,我们需要java.lang.reflect.InvocationHandler接口和java.lang.reflect.Proxy类的支持

首先我们先了解一下java.lang.reflect.InvcocatioHandler接口:

invocationHandler接口仅定义了一个方法

该方法第一个参数一般指代理类,第二个指被代理的方法,最后一个为该方法的参数

java.lang.reflect.Proxy类即为动态代理类,其主要包含以下内容:

Protected Proxy (invocationHandler h); //构造函数

Static Class getProxyClass (ClassLoader loader,Class[] interfaces)://获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口数组

Static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)://返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

下面我们来看如何使用动态代理

首先和之前相同的接口,原类。

/**
 *  @Author SZF
 *
 * @Date 2018-08-09
 *
 */
    //抽象接口
    public interface WantCar {
         void canRun();
         void canFly();
    }
    //原类
    public class PrimaryCar implements WantCar {
        public void canRun() {
            System.out.println("I can run!");
        }
        public void canFly() {
            System.out.println("I can fly!");
        }
    }

接着定义一个动态代理类,我们动态代理类必须要实现invocationHandler 接口:

 

 

public class DynamicProxy implements InvocationHandler{
    // 我们要代理的真实对象
    private PrimaryCar pCar;
    
    //    构造方法,给我们要代理的真实对象赋初值
    public DynamicProxy(PrimaryCar pCar)
    {
        this.pCar= pCar;
    }
    
    @Override
    public Object invoke(PrimaryCar pCar, Method method, Object[] args)
            throws Throwable
    {    
        //    当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        method.invoke(wCar, args);
        //我们也可以延伸一些自己的方法
        System.out.println("I can do anything!");
        return null;
    }

}

最后,我们于Client进行调用:

 newProxyInstance()具体实现之后再作更深入的讨论。

package test;
/**
 *  @Author SZF
 *
 * @Date 2018-08-09
 *
 */
public class test {
    
    public static void main(String[] args) {
        PrimaryCar pCar=newprimaryCar();
        DynamicProxy dCar=new DynamicProxy(pCar);
        WantCar wcar=new (WantCar) dCar.newProxyInstance(pCar.getClass().getClassLoader(),
                     pCar.getClass().getInterfaces(),dCar);
        System.out.println(wcar.run());
 }    
}

输出:

I can run!

I can do anything!

 

参考:百度百科

 

posted @ 2018-08-10 10:27  Atseas  阅读(141)  评论(0)    收藏  举报