23种设计模式之代理模式

意图

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

适用性

适用代理模式常见情况:
1.远程代理(Remote Proxy)为一个对象在不同的地址空间提供局部代表;
2.虚代理(Virtual Proxy)根据需要创建开销很大的对象,比如我们从网站上下载一张大图时,可以先显示默认图,下载完成后再显示真正的图;
3.保护代理(Protection Proxy)控制对原始对象的访问,用于对象应该有不同的访问权限的时候。
4.智能指引(Smart Reference)取代了简单的指针,在访问对象时执行一些附加操作。它的典型用途包括:
1)对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它。
2)当第一次引用一个持久对象时,将它装入内存。
3)在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。

类图

image.png

角色介绍

Subject:抽象主题类,该类的主要职责是声明真实主题和代理的共同接口方法,该类既可以是一个抽象类,也可以是一个接口。
RealSubject:真实主题类,该类也被称为委托类或被代理类,该类定义了代理所表示的真实对象,由其执行具体的业务逻辑方法。
Proxy:代理类,该类持有一个对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行,以此起到代理的作用。

生活中的示例

生活当中有很多需要别人代理的事情,比如打官司,请律师代理诉讼;打游戏,请代练等等。这里以请保姆照看小孩为例,当父母都要上班忙不过来时,需要请保姆照看小孩,给小孩穿衣服,喂饭 ,洗澡等。

类图

image.png

注:图中Parents类和BabySitter类是实现接口,要用虚线+三角箭头,但是ProcessOn上面没有虚线的选项,这里用的实线。

IWatchBaby接口:对应于Subject,定义出了共同接口方法;
Parents类: 对应于RealSubject;
BabySitter类:保姆,对应于Proxy类,它持有一个Parents的引用。

代码:
Client.java

package com.sunny.disignpattern.proxy;

/**
 * @ProjectName: DesignPattern23
 * @Package: com.sunny.disignpattern.proxy
 * @ClassName: Client
 * @Description: 客户类
 * @Author: Sunny
 * @CreateDate: 2020/6/25 10:18 AM:
 */
public class Client {
    public static void main(String[] args) {
        Parents parents = new Parents();
        BabySitter babySitter = new BabySitter(parents);
        babySitter.getBath();
        babySitter.dress();
        babySitter.feed();
    }
}

IWatchBaby.java

package com.sunny.disignpattern.proxy;

/**
 * @ProjectName: DesignPattern23
 * @Package: com.sunny.disignpattern.proxy
 * @ClassName: IWatchBaby
 * @Description: 照看小孩的公共接口
 * @Author: Sunny
 * @CreateDate: 2020/6/25 10:13 AM:
 */
public interface IWatchBaby {
    void dress();

    void getBath();

    void feed();
}

Parents.java

package com.sunny.disignpattern.proxy;

/**
 * @ProjectName: DesignPattern23
 * @Package: com.sunny.disignpattern.proxy
 * @ClassName: Parents
 * @Description: 父母类
 * @Author: Sunny
 * @CreateDate: 2020/6/25 10:13 AM:
 */
public class Parents implements IWatchBaby {
    @Override
    public void dress() {
        System.out.println("给小孩穿衣服");
    }

    @Override
    public void getBath() {
        System.out.println("给小孩洗澡");
    }

    @Override
    public void feed() {
        System.out.println("给小孩喂饭");
    }
}

BabySitter.java

package com.sunny.disignpattern.proxy;

/**
 * @ProjectName: DesignPattern23
 * @Package: com.sunny.disignpattern.proxy
 * @ClassName: BabySitter
 * @Description: 保姆类
 * @Author: Sunny
 * @CreateDate: 2020/6/25 10:15 AM:
 */
public class BabySitter implements IWatchBaby {
    Parents parents;

    public BabySitter(Parents parents) {
        this.parents = parents;
    }


    @Override
    public void dress() {
        parents.dress();
    }

    @Override
    public void getBath() {
        parents.getBath();
    }

    @Override
    public void feed() {
        parents.feed();
    }
}

Android源码中的示例

基于Android9.0源码:
当应用通过ActivityManager访问ActivityManagerService的接口方法时,本质上是通过IActivityManager的代理对象访问的,是一种典型的代理模式。
IActivityManger.aidl接口如下:

interface IActivityManager {
    //......省略部分代码......
    int startActivity(in IApplicationThread caller, in String callingPackage, in Intent intent,
            in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode,
            int flags, in ProfilerInfo profilerInfo, in Bundle options);
  //......省略部分代码......
}

接口真正的实现都在ActivityManagerService。
ActivityManagerService.java部分代码

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  //......省略部分代码......
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
 //......省略部分代码......
}

可见ActivityManagerService继承于IActivityManager.Stub-是IActivityManager.aidl 生成的java文件的内部抽象类。

在看ActivityManager.java中通过getService方法拿到IActivityManager对象。

public class ActivityManager {
  //.......省略部分代码......
   * @hide
     */
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
  //......省略部分代码......
}

拿到IActivityManager对象后,调用IActivityManager接口就像直接调用ActivityManagerService一样。实际上,中间还有一个跨进程的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值