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

Android设计模式-代理模式

作者: 星宇V | 来源:发表于2019-10-22 18:09 被阅读0次

    UML关系简单介绍
    UML简单使用的介绍
    创建型设计模式
    Android设计模式-单例模式
    Android设计模式-工厂模式
    Android设计模式-抽象工厂模式
    Android设计模式-建造者模式
    Android设计模式-原型模式
    结构型设计模式
    Android设计模式-代理模式
    Android设计模式-装饰模式
    Android设计模式-适配器模式
    Android设计模式-组合模式
    Android设计模式-门面模式
    Android设计模式-桥接模式
    Android设计模式-享元模式
    行为型设计模式
    Android设计模式-策略模式
    Android设计模式-命令模式
    Android设计模式-责任链模式
    Android设计模式-模版方法模式
    Android设计模式-迭代器模式
    Android设计模式-观察者模式
    Android设计模式-备忘录模式
    Android设计模式-中介者模式
    Android设计模式-访问者模式
    Android设计模式-状态模式
    Android设计模式-解释器模式

    1.定义

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

    2.代理模式通用类图

    代理模式通用类图

    角色介绍

    • Subject 抽象主题,可以是抽象类也可以是接口,realsubject和proxy都是继承或者实现自它。
    • RealSubject 真实主题类,也就是被代理者,也就是具体任务逻辑的执行者
    • Proxy 代理类,也叫委托类,一般持有真实主题类的引用,在相应的方法中,调用真实主题类的对应方法。

    3.简单实现

    3.1抽象主题类

    public interface Subject {
        void doSomething();
    }
    

    3.2 真实主题类

    public class RealSubject implements Subject {
        @Override
        public void doSomething() {
            System.out.println("买肉!");
        }
    }
    

    3.3 代理类

    public class ProxySubject implements Subject {
        Subject subject=null;
    
        public ProxySubject(Subject subject) {
            this.subject = subject;
        }
    
        @Override
        public void doSomething() {
            doBefore();
            System.out.println("我代理者,我要!!");
            this.subject.doSomething();
            doAfter();
        }
    
        private void doBefore(){
            System.out.println("我是代理者前置动作");
    
        }
    
        private void doAfter(){
            System.out.println("我是代理者后置动作");
    
        }
    }
    

    3.4场景调用

    public class MyClass {
        public static void main(String args[]) {
            Subject realSubject=new RealSubject();
            Subject proxySubject=new ProxySubject(realSubject);
            proxySubject.doSomething();
        }
    }
    
    打印结果为
    
    我是代理者前置动作
    我代理者,我要!!
    买肉!
    我是代理者后置动作
    
    

    3.5例子简介

    被代理类realSubject与代理类proxySubject都实现了接口Subject,比如你想去买肉吃了,realSubject就是你,但是你不想动弹,就让你都舍友帮你去买肉回来,proxySubject就相当于你的舍友。你舍友肯定是要知道他是帮谁买肉的,否则回来谁给钱呀。。这个目标就是通过构造函数传过来的subject,也就是在场景类中传过来的realSubject。另外代理模式,也常可在代理的方法执行前后,插入一些自己的逻辑,比如上例中的doBefore和doAfter。

    4.扩展

    4.1普通代理和强制代理

    普通代理就是我们要知道代理的存在,也就是代理类后才能访问。而强制代理则是调用者直接调用真实角色而不用关心代理是否存在,其代理的产生是由真实角色决定的

    4.1.1普通代理

    修改上面的例子,将其改为普通代理模式

    4.1.1.1 抽象主题类

    public interface Subject {
        void doSomething();
    }
    

    4.1.1.2 真实主题类

    public class RealSubject implements Subject {
    
        public RealSubject(Subject subject) throws Exception{
            if (subject==null){
                throw new Exception();
            }
        }
    
        @Override
        public void doSomething() {
            System.out.println("买肉!");
        }
    }
    

    4.1.1.3 代理类

    public class ProxySubject implements Subject {
        private Subject subject=null;
    
        public ProxySubject() {
            try {
                subject=new RealSubject(this);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    
        @Override
        public void doSomething() {
            doBefore();
            System.out.println("我代理者,我要!!");
            this.subject.doSomething();
            doAfter();
        }
    
        private void doBefore(){
            System.out.println("我是代理者前置动作");
    
        }
    
        private void doAfter(){
            System.out.println("我是代理者后置动作");
    
        }
    }
    

    4.1.1.4 场景调用

    public class MyClass {
        public static void main(String args[]) {
    
            Subject proxySubject=new ProxySubject();
            proxySubject.doSomething();
        }
    }
    
    打印结果为
    
    我是代理者前置动作
    我代理者,我要!!
    买肉!
    我是代理者后置动作
    

    4.1.1.5 例子总结

    从打印结果中,可以看出,在该模式下,没有发生变化,但是在调用的时候,只需要调用代理类就可以进行相应的任务,不用知道具体的真实主题类是谁。屏蔽了真实角色的变更对高层模块的影响,真实主题类想怎么修改就怎么修改,对高层次模块没有任何影响,只要你实现了对应的方法,对扩展性较高对场合特别适合。

    4.1.2 强制代理

    强制代理简单理解为就是必须通过真实主题类获得的代理,才能进行相应的操作。就相当于高层模块new了一个真实主题类,但是返回的确实一个代理角色。
    将上面的例子修改为强制代理

    4.1.2.1 抽象主题类

    public interface Subject {
        void doSomething();
    }
    

    4.1.2.2 真实主题类

    public class RealSubject implements Subject {
        private Subject proxySubject=null;
    
        public RealSubject() {
    
        }
    
        public Subject getProxySubject(){
            this.proxySubject=new ProxySubject(this);
            return this.proxySubject;
        }
    
        @Override
        public void doSomething() {
            if (proxySubject!=null) {
                System.out.println("买肉!");
            }else {
                System.out.println("请使用指定的代理进行访问");
            }
    
        }
    }
    

    4.1.2.3 代理类

    public class ProxySubject implements Subject {
        private Subject subject=null;
    
        public ProxySubject(Subject subject) {
            this.subject = subject;
        }
    
        @Override
        public void doSomething() {
            doBefore();
            System.out.println("我代理者,我要!!");
            this.subject.doSomething();
            doAfter();
        }
    
        private void doBefore(){
            System.out.println("我是代理者前置动作");
    
        }
    
        private void doAfter(){
            System.out.println("我是代理者后置动作");
    
        }
    }
    

    4.1.2.4 场景调用

    public class MyClass {
        public static void main(String args[]) {
    
            Subject real=new RealSubject();
            real.doSomething();
        }
    }
    
    打印结果为
    请使用指定的代理进行访问
    
    public class MyClass {
        public static void main(String args[]) {
    
            Subject real=new RealSubject();
            Subject proxy=new ProxySubject(real);
            proxy.doSomething();
        }
    }
    打印结果为
    我是代理者前置动作
    我代理者,我要!!
    请使用指定的代理进行访问
    我是代理者后置动作
    
    public class MyClass {
        public static void main(String args[]) {
    
            Subject real=new RealSubject();
            Subject proxy=((RealSubject) real).getProxySubject();
            proxy.doSomething();
        }
    }
    打印结果为
    我是代理者前置动作
    我代理者,我要!!
    买肉!
    我是代理者后置动作
    

    4.1.2.5例子总结

    以上的例子即为强制代理,调用的时候,只能通过真实角色指定的代理角色,才能访问具体的功能逻辑,不允许直接访问真实角色。高层模块只要调用getProxySubject就可以获取访问真实角色的指定代理类,不需要重新产生一个新的代理类。

    4.2动态代理

    动态代理在实现阶段不管关心代理谁,而在运行阶段才指定代理那一个对象。现在很流行的一个aop编程,核心就是使用了动态代理技术。
    动态代理主要用到了InvocationHandler类

    4.2.1动态代理简单实现

    动态代理类

    public class DynamicProxy implements InvocationHandler {
        //被代理的对象
        private Object object;
    
        public DynamicProxy(Object object) {
            this.object = object;
        }
    
        @Override
        public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
            System.out.println("我是动态代理!");
            Object result=method.invoke(object,objects);
            return result;
        }
    }
    

    真实主题类

    修改回最初的样子。。。

    public class RealSubject implements Subject {
        private Subject proxySubject=null;
    
        public RealSubject() {
    
        }
    
    //    public Subject getProxySubject(){
    //        this.proxySubject=new ProxySubject(this);
    //        return this.proxySubject;
    //    }
    
        @Override
        public void doSomething() {
    //        if (proxySubject!=null) {
                System.out.println("买肉!");
    //        }else {
    //            System.out.println("请使用指定的代理进行访问");
    //        }
    
        }
    }
    

    场景类调用

    public class MyClass {
        public static void main(String args[]) {
    
            Subject real=new RealSubject();
            DynamicProxy dynamic=new DynamicProxy(real);
            ClassLoader classLoader=real.getClass().getClassLoader();
            Subject dynamicSubject= (Subject) Proxy.newProxyInstance(classLoader,new Class[]{Subject.class},dynamic);
            dynamicSubject.doSomething();
        }
    }
    
    打印结果为
    ,
    我是动态代理!
    买肉!
    

    动态代理总结

    动态代理是在程序运行期间根据反射等机制动态的生成。代理类和委托类的关系是在程序运行期确定的。
    另外动态代理如果想要在相应位置添加前后操作,则可以在动态代理类中添加

     @Override
        public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
            System.out.println("我是动态代理!");
            if (method.getName().equalsIgnoreCase("doSomething")){
                System.out.println("插入点什么??");
            }
            Object result=method.invoke(object,objects);
            return result;
        }
    
    打印结果为
    我是动态代理!
    插入点什么??
    买肉!
    

    本质上,这就是aop,具体aop的东西自行搜索吧,这里扯远了。。

    总结

    代理模式是常用的结构型设计模式之一,它为对象的间接访问提供了一个解决方案,可以对对象的访问进行控制

    优点

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

    相关文章

      网友评论

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

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