设计模式

代理模式

2019-07-29  本文已影响0人  随心录

代理模式

代理模式也称委托模式,是结构型设计模式之一。是应用广泛的模式之一

定义

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

使用场景

当无法或不想直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口

UML类图

图1

简单实现

例子:以小民诉讼的流程举例。那么需要代理律师代理,诉讼简单流程:提交申请–>进行举证–>开始辩护–>诉讼完成

诉讼接口类

public interface ILawsuit {

    /**
     * 提交申请 
     */
    void submit();

    /**
     * 进行举证 
     */
    void burden();

    /**
     * 开始辩护
     */
    void defend();

    /**
     * 诉讼完成
     */
    void finish();
}

具体诉讼人小民:

public class XiaoMin 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("诉讼成功,判决老板即日起七天内结算工资!");
    }

}

代理律师:

public class Lawyer implements ILawsuit{

    private ILawsuit mLawsuit; //持有一个具体被代理者的引用

    public Lawyer(ILawsuit lawsuit) {
        this.mLawsuit = lawsuit;
    }

    @Override
    public void submit() {
        mLawsuit.submit();
    }

    @Override
    public void burden() {
        mLawsuit.burden();
    }

    @Override
    public void defend() {
        mLawsuit.defend();
    }

    @Override
    public void finish() {
        mLawsuit.finish();
    }

}

开始仲裁:

public class Client {
    public static void main(String[] args) {
        //构造出诉讼人小民
        ILawsuit xiaomin = new XiaoMin();

        //构造一个代理律师,并将小民传递进去
        ILawsuit lawyer = new Lawyer(xiaomin);

        //律师提交申请
        lawyer.submit();

        //律师进行举证
        lawyer.burden();

        //律师代小民辩护
        lawyer.defend();

        //完成诉讼
        lawyer.finish();
    }
}

结果:

老板年底拖欠工资,特此申请仲裁!
这是合同书和过去一年的银行工资流水!
证据确凿,不需要再说什么!
诉讼成功,判决老板即日起七天内结算工资

同样我们也可以代理其他人,只需要实现ILawsuit即可。上面的代理模式也叫静态代理,也就是在代码运行前代理类的class文件就已经存在。那么相反,当然也会有动态代理,下面用动态代理实现上述例子:

Java提供了一个便捷的动态代理接口InvocationHandler,我们来实现它

public class DynamicPorxy implements InvocationHandler{

    private Object obj; //被代理类的引用

    public DynamicPorxy(Object obj) {
        this.obj = obj;
    }

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

}

这里我们通过invoke方法来调用具体的被代理方法
修改后的Client类:

public class Client {
    public static void main(String[] args) {
        //构造出诉讼人小民
        ILawsuit xiaomin = new XiaoMin();

        //1.静态代理
        //构造一个代理律师,并将小民传递进去
        //ILawsuit lawyer = new Lawyer(xiaomin);

        //--------------------------------------
        //2.动态代理
        //构造一个动态代理
        DynamicPorxy proxy = new DynamicPorxy(xiaomin);

        //获取被代理类小民的ClassLoader
        ClassLoader loader = xiaomin.getClass().getClassLoader();

        //动态构造一个代理者律师
        ILawsuit lawyer = (ILawsuit) Proxy.newProxyInstance(loader, new Class[]{ ILawsuit.class }, proxy);

        //律师提交申请
        lawyer.submit();

        //律师进行举证
        lawyer.burden();

        //律师代小民辩护
        lawyer.defend();

        //完成诉讼
        lawyer.finish();
    }

结果不变,由此可以看出动态代理通过一个代理类来处理N多个被代理类,其实质是对代理者与被代理者解耦。相对而言静态代理则只能为给定接口下的实现类做代理,如果接口不同那么就需要重新定义不同的代理类,较为复杂,但是静态代理更符合面向对象原则。具体使用哪种方式,根据个人喜好

Android源码中的代理模式实现

ActivityManagerProxy代理类
ActivityManagerAndroid中管理和维护Activity的相关信息的类,为了隔离它与ActivityManagerService,有效降低二者的耦合,在这中间使用了ActivityManagerProxy代理类,所有对ActivityManagerService的访问都转换成对代理类的访问,这样ActivityManager就与ActivityManagerService解耦了

总结

优点

缺点

上一篇下一篇

猜你喜欢

热点阅读