Android 设计模式之代理模式

本文是自己关于代理模式的一篇学习笔记,参考于 Android 源码设计模式解析与实战

1. 定义

当我们无法不想直接访问某个对象或访问某个对象存在困难的时候,我们可以通过委托代理一个对象来间接访问,所以代理模式也称为委托模式

1.1 代理模式的UML类图

代理模式UML类图

  • Subject: 抽象主题类, 用于声明真实主题与代理主题的共同接口方法,可以是一个抽象类也可以是一个接口。
  • RealSubject: 真实主题类,也称为被委托类或被代理类, 用于定义代理所表示的真实对象。
  • ProxySubject: 代理主题类, 也称为委托类, 该类持用真实主题类的引用,在其所实现的接口方法中调用真实主题类的接口方法,从而起到中间代理的作用。
  • Client: 客户端类,即使用代理类的对象类。

1.1.1 代理模式的代码结构

Subject: 抽象主题类

/**
 * @author jere
 *
 * 抽象主题类
 */
public abstract class Subject {

    /**
     * 一个普通的抽象方法
     */
    public abstract void visit();
}

RealSubject: 真实主题类

/**
 * @author jere
 *
 * 实现抽象主题的真实主题类
 */
public class RealSubject extends Subject {
    private static final String TAG = "RealSubject";
    
    @Override
    public void visit() {
        Log.i(TAG, "visit: ");
    }
}

ProxySubject: 代理主题类

/**
 * @author jere
 *
 * 实现抽象主题类的代理类
 */
public class ProxySubject extends Subject {
    private static final String TAG = "ProxySubject";

    //持有真实主题的引用
    private RealSubject mRealSubject;

    public ProxySubject(RealSubject realSubject) {
        this.mRealSubject = realSubject;
    }

    @Override
    public void visit() {
        Log.i(TAG, "visit: ");
        //调用真实主题类中的 visit() 方法
        mRealSubject.visit();
    }
}

Client: 客户端类

public class ProxyPatternTestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        //构造一个真实主题实例
        RealSubject realSubject = new RealSubject();
        //构造一个代理主题实例,并且持有刚刚构造的真实主题实例
        ProxySubject proxySubject = new ProxySubject(realSubject);
        //调用代理主题实例的 visit() 方法
        proxySubject.visit();
    }
}

2. 代理模式的简单实现

在我们的生活中就存在很多的代理模式,比如绝大部分人都经历过的租房子,由于我们手上没有房源,很难租到心仪的房子,所以通常我们都是委托房产中介帮忙找房子,找到合适的房子后,我们支付中介费给房产中介。也有的人很忙,或者很懒,全权交给中介去帮我们干这些事。

简洁化一下流程,分成三个步骤:找房子 -> 联系房东 -> 签订合同

套入上述的代理模式结构中,就是:

  • Subject:抽象主题 -> 租房子的步骤 -> IRentHouse.java
  • RealSubject: 被代理类 -> 租客 -> Renter.java
  • ProxySubject:代理类 -> 房产中介 -> HouseAgent.java
  • Client: 客户端 -> 租房子事件 -> RentHouseTestActivity.java

代理模式例子 - 租房子

2.1 具体代码

Subject:抽象主题 -> 租房子的步骤 -> IRentHouse.java

/**
 * @author jere
 * <p>
 * Subject: 租房接口
 */
public interface IRentHouse {

    /**
     * 找房子
     */
    void findHouse();

    /**
     * 联系房东
     */
    void contactLandlord();

    /**
     * 签订合同
     */
    void signContract();
}

RealSubject: 被代理类 -> 租客 -> Renter.java

/**
 * @author jere
 * <p>
 * RealSubject: 租客
 */
public class Renter implements IRentHouse {
    private static final String TAG = "Renter";

    @Override
    public void findHouse() {
        Log.i(TAG, "findHouse: ");
    }

    @Override
    public void contactLandlord() {
        Log.i(TAG, "contactLandlord: ");
    }

    @Override
    public void signContract() {
        Log.i(TAG, "signContract: ");
    }
}

ProxySubject:代理类 -> 房产中介 -> HouseAgent.java

/**
 * @author jere
 * <p>
 * ProxySubject: 房产中介
 */
public class HouseAgent implements IRentHouse {
    /**
     * 被代理对象 -> 租客
     */
    private IRentHouse mRenter;

    public HouseAgent(IRentHouse renter) {
        this.mRenter = renter;
    }

    @Override
    public void findHouse() {
        mRenter.findHouse();
    }

    @Override
    public void contactLandlord() {
        mRenter.contactLandlord();
    }

    @Override
    public void signContract() {
        mRenter.signContract();
    }
}

Client: 客户端 -> 租房子事件 -> RentHouseTestActivity.java

/**
 * @author jere
 *
 * Client :租房子
 */
public class RentHouseTestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //租客 -》明明
        Renter mingMing = new Renter();

        //明明找了房产中介 -》小李,委托他帮忙租一个房子
        HouseAgent xiaoLi = new HouseAgent(mingMing);

        //小李开始找房子
        xiaoLi.findHouse();

        //小李找到房子后联系房东
        xiaoLi.contactLandlord();

        //小李找到房子后替明明与房东签订合同
        xiaoLi.signContract();
    }
}

2.2 动态代理

上述的例子是静态代理实现方式,接着我们用动态代理来实现一下。

创建动态代理类:

/**
 * @author jere
 * <p>
 * 动态代理类
 */
public class DynamicProxy implements InvocationHandler {
    //被代理类
    private Object object;

    public DynamicProxy(Object o) {
        this.object = o;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //调用被代理类对象的方法
        return method.invoke(object, args);

    }
}

然后我们就可以在我们的 Client 客户端,利用动态代理来动态创建一个代理类 -》 房产中介-小李,如下:

/**
 * @author jere
 *
 * Client :租房子
 */
public class RentHouseTestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        //被代理类:租客 -》明明
        Renter mingMing = new Renter();

        //构造一个动态代理
        DynamicProxy dynamicProxy = new DynamicProxy(mingMing);
        //获取被代理类 明明 的 classLoader
        ClassLoader classLoader = mingMing.getClass().getClassLoader();

        //动态构造一个代理类 房产中介 小李
        IRentHouse xiaoLi = (IRentHouse) Proxy.newProxyInstance(classLoader, new Class[] {IRentHouse.class}, dynamicProxy);
        //小李开始找房子
        xiaoLi.findHouse();
        //小李找到房子后联系房东
        xiaoLi.contactLandlord();
        //小李找到房子后替明明与房东签订合同
        xiaoLi.signContract();


    }
}

再次说明:本文参考于 Android 源码设计模式解析与实战

源代码见 AndroidDesignPattern

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值