代理模式

一、定义

代理模式是为其他对象提供一种代理以控制这个对象的访问,一般是不想直接访问某个对象或无法访问到时,可以通过一个代理对象间接访问。

二、实现

代理模式有两种:静态代理和动态代理,我们先来看下静态代理。

这里我们以代驾为例,正常情况下我们可以自己开车,但喝了酒的情况下,就得找一个代驾了,否则将面临罚款扣分和吊销驾照等处罚。

不管是自己开车或叫代驾,两者做的事情本质都相同,那就是开车。所以我们可以先定义委托对象与代理对象需要实现相同的接口。

/**
 * 抽象主题类
 */
public interface IDrive {
    //开车
    void drive();
}

接着我们定义一个具体的实现类ZhangSan

/**
 * 具体主题类
 */
public class ZhangSan implements IDrive {

    @Override
    public void drive() {
        System.out.println("开车中...");
    }
}

平时都是ZhangSan自己开车上下班,某天公司聚餐,喝了点小酒,ZhangSan得找一个代驾,于是代理类来了。

/**
 * 代理类
 */
public class DiDiDriver implements IDrive {

    //持有IDrive对象的引用
    private IDrive iDrive;

    public DiDiDriver(IDrive iDrive) {
        this.iDrive = iDrive;
    }

    @Override
    public void drive() {
        iDrive.drive();
    }
}

这里的代理类DiDiDriver持有IDrive对象的引用,调用时需要传递一个被代理的对象进来,最后我们看下测试类:

public class Test {

    public static void main(String[] args) {

        //定义ZhangSan对象
        IDrive zhangsan = new ZhangSan();
        //DiDi代驾
        IDrive diDiDriver = new DiDiDriver(zhangsan);
        diDiDriver.drive();
    }
}

打印结果:开车中...

 

到这里我们思考一个问题,代理类还可以代理其他人吗?当然是可以的,只需要再定义一个类LiSi实现IDrive接口,然后再修改调用的代码,也可以实现。

我们在前面说过代理模式还有一种是动态代理,静态代理是在编译时就已经确定是为谁代理,而动态代理是根据运行时决定。在Java中给我们提供了一个动态代理接口

InvocationHandler,实现该接口并重写invoke方法。

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 {
        //调用被代理类对象的方法
        Object result = method.invoke(object, args);
        return result;
    }
}

最后我们看下动态代理的测试类怎么写

public class Test {

    public static void main(String[] args) {

        //定义ZhangSan对象
        IDrive zhangsan = new ZhangSan();
        //构造一个动态代理
        DynamicProxy dynamicProxy = new DynamicProxy(zhangsan);
        //获取被代理类ZhangSan的ClassLoader
        ClassLoader classLoader = zhangsan.getClass().getClassLoader();
        //动态创建一个DiDi代驾
        IDrive diDiDriver = (IDrive) Proxy.newProxyInstance(classLoader, new Class[]{IDrive.class}, dynamicProxy);
        diDiDriver.drive();
    }
}

结果跟静态代理是一样的,动态代理可以通过一个代理类来代理多个被代理类,达到代理类和被代理类解耦的目的。静态代理只能为给定接口下的实现类做代理,如果接口不同,则需要创建新的代理类。

三、代理模式和装饰模式的区别

代理模式和装饰模式比较类似,但我们需要知道它们本质的区别:装饰模式是在具体的组件实现类中扩展了自己的方法,最后调用的是装饰者自己的方法;代理模式,顾名思义,只是一个代理,不会有扩展方法,同时调用的也是被代理类的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值