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

设计模式-代理模式

作者: KevinLive | 来源:发表于2017-08-11 13:29 被阅读31次
    代理模式 UML
    • Subject(抽象类):声明代理角色和真实角色共同的接口,可以是抽象类或接口
    • Proxy(代理类):持有真实对象的引用,通常,在代理类中,客户端在调用所引用的真实对象之前或之后还需要执行其他操作,不仅仅是调用真实对象中的操作
    • RealSubject(真实类):真实对象的业务操作

    下面是代理模式的一个简单实现:

    Subject 类:

    interface Subject {
        void request();
    }
    

    RealSubject 类:

    class RealSubject implements Subject {
        @Override
        public void request() {
            LogUtils.i("我是真实对象");
        }
    }
    

    Proxy 类:

    public class Proxy implements Subject {
    
        private RealSubject mRealSubject;
    
        public Proxy() {
            mRealSubject = new RealSubject();
        }
        
        @Override
        public void request() {
            LogUtils.i("调用真实对象前");
            mRealSubject.request();
            LogUtils.i("调用真实对象后");
        }
    }
    

    猛的一看和 装饰模式 非常的相似,装饰模式中的具体组件类(ConcreteComponent)和装饰类(Decorator)都实现同一个接口,代理模式中的抽象类(Subject)和代理类(Proxy)也是实现同一个接口,装饰类(Decorator)和代理类(Proxy)都是在真实对象的方法前面或者后面添加方法,但实际上,这两个模式还是又本质上的区别,装饰模式用于给一个对象动态添加方法,而代理模式用于控制一个对象的访问,隐藏对象的具体信息,代理模式中代理对象和真实对象间的关系在编译器就已经确定,而装饰模式是通过构造器传递,运行期才能确定,下面是 装饰类(Decorator) 的部分代码,对比 代理类(Proxy) 的代理就很清晰了

    public class Decorator extends Component {
    
        private Component component;
    
        // 通过构造器传递对象
        public Decorator(Component component) {
            this.component = component;
        }
    }
    

    看完代理模式和装饰模式的区别,再来了解一下代理模式中的动态代理,上面是静态代理的例子,代理对象在编译期就已经存在;而动态代理不同于静态代理,动态代理通过反射机制在运行期动态生成代理对象,Java 中提供了一个 InvocationHandler 接口实现动态代理,下面是示例代码:

    DynamicProxy 类:

    public class DynamicProxy implements InvocationHandler {
    
        private Subject subject;
    
        public DynamicProxy(Subject subject) {
            this.subject = subject;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            LogUtils.i("方法调用前");
            Object invoke = method.invoke(subject, args);
            LogUtils.i("方法调用后");
            return invoke;
        }
    }
    

    静态代理 Client 类:

    Proxy proxy = new Proxy();
    proxy.request();
    

    动态代理 Client 类:

    Subject realSubject = new RealSubject();
    DynamicProxy dynamicProxy = new DynamicProxy(realSubject);
    Subject subject = (Subject)java.lang.reflect.Proxy.newProxyInstance(RealSubject.class.getClassLoader(), RealSubject.class.getInterfaces(),dynamicProxy);
    subject.request();
    

    优点

    • 协调调用者和被调用者,一定程度上降低系统耦合
    • 客户端可针对抽象类进行编程,增加和替换代理类无须修改源代码,符合开闭原则,系统具有较好的灵活性和可扩展性

    缺点

    • 客户端和真实对象之间增加了代理对象,有些类型的代理模式可能会造成请求的处理速度变慢,例如保护代理
    • 实现代理模式需要额外的工作量,有些代理模式实现过程较为复杂,例如远程代理

    适用场景

    • 需要控制对一个对象的访问,为不同调用者提供不同级别的访问权限
    • 需要为一个对象提供一些额外的操作

      源码地址:Github

    相关文章

      网友评论

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

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