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
  • 相关阅读:
    govendor用法
    java.util.DualPivotQuickSort的实现
    windows注册表
    一道正则表达式题目
    JDK10、JDK11、JDK12新特性
    初夏清晨有所思
    Java 9新特性
    sklearn聚类评价指标
    沉浸式和全局式
    [抄]外部奖励对内在动机的侵蚀
  • 原文地址:https://www.cnblogs.com/vegetate/p/9997259.html
Copyright © 2011-2022 走看看