Android设计模式-代理模式

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.代理模式通用类图

Android设计模式-代理模式_第1张图片
代理模式通用类图

角色介绍

  • 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设计模式-代理模式)