美文网首页Design Pattern
设计模式-代理模式

设计模式-代理模式

作者: MonkeyLqj | 来源:发表于2020-05-09 22:57 被阅读0次

    1.代理模式的介绍

    代理模式(Proxy Pattern)也称为委托模式,是结构型设计模式的一种。在我们生活中代理模式是非常常见的,比如我们让同事帮忙买饭,房屋中介等都是一种代理模式。也就是让别人给自己干活。

    2.代理模式的定义

    为其他对象提供一种代理以控制对这个对象的访问。

    3.代理模式的UML类图

    代理模式
    • Subject: 抽象角色指真实角色和代理角色共有的接口。
    • RealSubject: 真实角色需要实现抽象接口,定义真实角色所要实现的业务逻辑,以供代理角色调用。
    • ProxySubject: 代理角色也需要实现抽象接口,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。

    4.静态代理模式的实现

    通过让朋友代买水果,来实现代理模式:
    第一步:先创建一个买水果的接口 (抽象角色)

    package com.monkey.designmode.proxy;
    /**
     * Created by Monkey on 2020/5/9.
     * Description:  买水果的接口
     */
    public interface IBuyFruit {
        void buyFruit();
    }
    

    第二步:实现买水果的接口 (真实角色)

    package com.monkey.designmode.proxy;
    
    /**
     * Created by Monkey on 2020/5/9.
     * Description:  具体的实现类,实现买水果的接口
     */
    public class Monkey implements IBuyFruit {
        @Override
        public void buyFruit() {
            System.out.println("我在果园里买水果");
        }
    }
    

    第三步:创建一个代理对象 (代理角色)

    package com.monkey.designmode.proxy;
    
    /**
     * Created by Monkey on 2020/5/9.
     * Description:代理类 持有一个被代理者的引用
     */
    public class BuyFruitProxy implements IBuyFruit {
    
        private IBuyFruit iBuy;
    
        public BuyFruitProxy(IBuyFruit iBuy) {
            this.iBuy = iBuy;
        }
    
        @Override
        public void buyFruit() {
            iBuy.buyFruit();
        }
    }
    

    客户端

    package com.monkey.designmode.proxy;
    
    public class ProxyClient {
        public static void main(String[] args) {
            IBuyFruit monkey = new Monkey();
            BuyFruitProxy proxy = new BuyFruitProxy(monkey);
            proxy.buyFruit();
        }
    }
    

    这就是一个简单的静态代理模式,真实对象将方法的执行委托给代理对象去完成。

    5.动态代理模式的实现

    我们在静态代理的基础上实现动态代理模式,在这里我们需要创建一个动态处理器,帮我们创建一个代理类,而不需要静态代理中的 BuyFruitProxy 代理类了。动态代理是在运行时利用反射的机制动态生成代理者的对象。

    创建一个动态代理类

    package com.monkey.designmode.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * Created by Monkey on 2020/5/9.
     * Description:动态代理类
     */
    public class DynamicProxy implements InvocationHandler {
        private Object object;
    
        public DynamicProxy(Object object) {
            this.object = object;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //调用被代理对象的方法
            Object result = method.invoke(object,args);
            return result;
        }
    }
    

    在动态代理类中我们声明一个Object的引用,指向被代理类,我们调用被代理类的具体方法在invoke()方法中执行。
    客户端

    package com.monkey.designmode.proxy;
    
    import java.lang.reflect.Proxy;
    
    public class ProxyClient {
        public static void main(String[] args) {
    
            IBuyFruit monkey = new Monkey();
            //构造一个动态代理
            DynamicProxy dynamicProxy = new DynamicProxy(monkey);
            ClassLoader classLoader = monkey.getClass().getClassLoader();
            //动态构造一个代理者
            IBuyFruit  proxy = (IBuyFruit) Proxy.newProxyInstance(classLoader,
                    new Class[]{IBuyFruit.class},dynamicProxy);
            proxy.buyFruit();
        }
    }
    

    Proxy.newProxyInstance()方法接受三个参数:

    • ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法是固定的
    • Class<?>[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型
    • InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法

    使用动态代理很好的对代理者与被代理者进行解耦,使两者之间没有了直接的耦合;其中静态代理只能对给定的接口下的实现类做代理。而静态代理更符合面向对象的原则。

    6.总结

    通过引入代理对象的方式间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性。通过代理对象对原有的业务增强,而不影响原有的业务。

    我们用通俗易懂的方式来理解下静态代理和动态代理的区别,我们在需要别人帮忙的时候,会提前给别人说好之后,才会给我们帮忙,这就是静态代理模式;而我们在需要帮忙的时候,直接告诉别人,现在就给我帮忙,这就是动态代理模式。

    相关文章

      网友评论

        本文标题:设计模式-代理模式

        本文链接:https://www.haomeiwen.com/subject/lbgcnhtx.html