设计模式:代理模式

一、前言

代理模式(Proxy Pattern),也称为委托模式,是一种常用的结构型设计模式。代理模式,在我们实际生活中也处处可见其例子,如:代理上网,海外代购,请律师打官司......

那么具体什么是代理模式呢?

一句话定义:为其他对象提供一种代理对象,已控制对这个对象的访问。

详细一点,即为其他对象提供代理,已控制对这个对象的访问,代理对象起到类似中介的作用,不设计功能服务,亦可增加额外服务。

二、代理模式的分类和实现方式

1、分类

远程代理:为一个位于不同地址空间的的对象提供一个本地的代理 。典型的设计有:C/S架构属于远程代理的缩影虚拟代理:如果要创建一个资源消耗较大的对象,可以先用一个代理对象表示,在真正需要的时候才真正创建。 。典型设计:经常我们看到很多APP在加载图片的时候,会先加载一个默认的图片,等真正的图片加载完了之后再显示出来,这样非常的友好。保护代理:控制用户的访问权限。典型设计:就像我们的公众号的文章留言功能,只有你这个用户关注了该公众号之后才能留言,否则你就只能浏览不能留言

2、实现方式

两种:静态代理和动态代理

三、UML图

Suject: 申明真实主题与代理的共同接口方法,既可以是个抽象类也可以是个接口(具有抽象方法)。    

RealSubject: 委托类或者被代理类,真实对象,实现了抽象方法,由其执行具体的业务逻辑。    

ProxySubject:持有一个对真实主题的引用,实现的接口方法中调用真实主题类中相应的方法执行,从而实现了代理。   

Client:客户类通过代理类间接地调用了真实主题类中定义的方法。

四、静态代理例子

新建一个起诉类接口:Subject

public interface ILawsuit {
    void submit();//提交申请
    void burden();//进行举证
    void defend();//开始辩护
    void finish();//诉讼完成
}

真正的起诉者:RealSubject

public class Civilian implements ILawsuit {
    @Override
    public void submit() {
        System.out.println("起诉");
    }
​
    @Override
    public void burden() {
        System.out.println("举证");
    }
​
    @Override
    public void defend() {
        System.out.println("辩护");
    }
​
    @Override
    public void finish() {
        System.out.println("胜诉");
    }
}

律师:ProxySubject

public class Lawyer implements ILawsuit {
    private ILawsuit civilian;
​
    public Lawyer(ILawsuit civilian) {
        this.civilian = civilian;
    }
​
    @Override
    public void submit() {
        civilian.submit();
    }
​
    @Override
    public void burden() {
        civilian.burden();
    }
​
    @Override
    public void defend() {
        civilian.defend();
    }
​
    @Override
    public void finish() {
        civilian.finish();
    }
}

客户端调用,调用律师的方法,通过律师调用真正的su起诉者的方法。

public class Client {
    public static void main(String[] args) {
        ILawsuit civilian = new Civilian();
        ILawsuit lawyer = new Lawyer(civilian);
        lawyer.submit();
        lawyer.burden();
        lawyer.defend();
        lawyer.finish();
    }
}

五、动态代理例子

上面的例子是一种静态代理,代理者的代码时先生成写好,然后再对其进行编译,在代码运行前,代理类的class编译文件就已经存在了 。

动态代理是相反的,通过反射动态的生成代理者对象,更灵活!也就是说在写代码的时候根本不知道要代理谁,具体代理谁会在执行阶段决定。

Java提供了一个便捷的动态代理接口InvocationHandler,动态代理类只要实现这个接口就行:

public class DynamicProxy implements InvocationHandler {
    private Object object;
​
    public DynamicProxy(Object object) {
        this.object = object;
    }
​
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //当然这里可以对方法名进行判断过滤 if(method.getName().equals("***"))
        Object result = method.invoke(object,args);
        return result;
    }
}

我们通过 invoke 方法来调用具体的真实的方法,object 是被代理类,method 是被代理类的方法,args 是方法的参数 。

客户端调用:

public class Main {
    public static void main(String[] args) {
        ILawsuit lawsuit = new Civilian();
        DynamicProxy proxy = new DynamicProxy(lawsuit);
        ClassLoader loader = lawsuit.getClass().getClassLoader();
        //动态创建代理类,需要传入一个类加载器ClassLoader;一个你希望这个代理实现的接口列表,这里要代理ILawsuit接口;
        //和一个InvocationHandler的实现,也就是前面创建的proxy。
        ILawsuit lawyer = (ILawsuit) Proxy.newProxyInstance(loader,new Class[]{ILawsuit.class},proxy);
        lawyer.submit();
        lawyer.burden();
        lawyer.defend();
        lawyer.finish();
    }
}

动态代理并不局限与代理一个接口的实现,可以根据运行时传入的接口,动态的生成代理类,然后通过Method的invoke方法来执行被代理类的真实方法。非常灵活。

动态代理的意义

在不改变原来目标方法功能的前提下,可以在代理中增强自己功能代码。
当一个项目中,有一个功能是其他人写好的,你可以使用,但是不能满足我的需求,我需要再增加点代码,这次就需要使用代理来进行代码的增强,而不用改原来的代码。

感谢,以上例子来自 -> Android设计模式(十七)-代理模式 - 简书

六、Android源码中的代理模式分析

Android源码中有不少的代理模式实现,比如源码里的ActivityManagerProxy代理类 ,其具体代理的是 ActivityManagerNative的子类 ActivityManagerService。ActivityManagerService 的功能是负责四大组件的启动/切换/调度、进程的管理/调度 。

ActivityManagerProxyActivityManagerNative都是实现IActivityManager这个接口,IActivityManager就是抽象主题了,ActivityManagerProxy为代理类,而真实主题是ActivityManagerNative,而实际上ActivityManagerNative是个抽象类,真正的具体实现是在它的子类ActivityManagerService中。

这里的代理实质是个远程代理ActivityManagerProxyActivityManagerService是运行在不同的进程空间中的。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KWMax

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值