zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1131 Subway Map (30 分)
    PAT 甲级 1131 Subway Map (30 分)
    AcWing 906. 区间分组 区间贪心
    AcWing 907. 区间覆盖 区间贪心
  • 原文地址:https://www.cnblogs.com/vegetate/p/9997259.html
Copyright © 2011-2022 走看看