设计模式之代理模式

本文介绍了Java中的代理模式,包括静态代理和动态代理。静态代理通过创建代理类来限制对被代理对象的直接访问,保护内部信息。动态代理则利用反射机制,在运行时动态创建代理对象,可以代理任何实现了相同接口的对象。文章还探讨了动态代理与AOP的关系,并展示了如何使用工厂模式进一步封装代理对象的创建。
摘要由CSDN通过智能技术生成

代理模式定义为提供一种方式以限制对被代理对象的访问控制

也就是说不会让你直接接触到被代理对象,一切对外操作由代理对象来产生。

普通代理

在这里插入图片描述

如上图所示,就先来写一个代理类,SmsProxyService,以后发短信的操作就交给代理类来执行。

/**
 * @author lw
 * @date 2022/3/29 0029
 * @description  代理对象
 */
public class SmsProxyService implements SmsService {

    //需要代理的对象
    private SmsService smsService;

    public SmsProxyService(SmsService smsService){
        this.smsService = smsService;
    }

    @Override
    public void send(String toPhone, String content) {
        toPhone = "12306";
        smsService.send(toPhone,content);
    }
}

在代码中可以看到,里面有一个需要代理的对象,感觉这个代理类和装饰器的类SmsServiceDecorator一模一样,就换了一个名字而已。

调用者

SmsService smsService = new SmsServiceImpl();
SmsService smsProxyService = new SmsProxyService(smsService);
smsProxyService.send("187581367762","hello world");

看上面的代码,都自己new出来SmsServiceImpl对象了,那还需要把它放在代理对象里面么?

那为什么不直接用SmsServiceImpl对象中的方法呢?

再回顾一下代理的定义,不会让你直接接触到被代理对象,也就是说,你压根不能直接new被代理对象。

既然如此,那就用一个工厂产生代理对象出去。

/**
 * @author lw
 * @date 2022/3/29 0029
 * @description  代理工厂
 */
public class ProxyFactory {

    /**
     * 产生代理对象
     * @return
     */
    public static SmsService produceProxy(){
        return new SmsProxyService(new SmsServiceImpl());
    }
}


SmsService smsService = ProxyFactory.produceProxy();
smsService.send("187581367762","hello world");

如此一来,就由工厂产生代理对象,以达到保护被代理者的信息。

凡是能保护被代理者,能限制外界直接访问被代理者的,都可以认为是代理模式,不用局限于代码实现。

动态代理

所谓动态代理,就是不确定被代理对象,也就是说SmsProxyService代码里无法知道是代理了谁。

动态代理可以用Java自带的代理方式看,也可以用cglib动态代理方式熟悉。

Java动态代理

既然是动态代理,那自然要用到反射,被代理对象是不固定的,那就需要一个祖父出场(Object)。
在这里插入图片描述

public class DynamicProxyService implements InvocationHandler {

    private Object target;//被代理对象
    public DynamicProxyService(Object target){
        this.target = target;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(target,args);
        return result;
    }
}

//工厂的动态生成代理方式  ProxyFactory
public static Object produceProxy(Object target) {
        InvocationHandler handler = new DynamicProxyService(target);
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), handler);
}

可以看到这个动态代理取名并没有取DynamicProxySmsService之类的表示某种固定信息,表示这是一个通用的代理,他可以代理任何对象。

调用者
 SmsService smsService = (SmsService)ProxyFactory.produceProxy(new SmsServiceImpl());
 smsService.send("187581367762","hello world");

这样可以看到,就需要在调用时自己new SmsServiceImpl对象了,这样写代码很容易让程序员想起还有SmsServiceImpl这个类。

那么就加一个短信工厂呗,用短信工厂产生短信服务。

/**
 * @author lw
 * @date 2022/3/29 0029
 * @description  短信工厂
 */
public class SmsFactory {

    public static SmsService produceSms(){
        SmsService smsService = (SmsService)ProxyFactory.produceProxy(new SmsServiceImpl());
        return smsService;
    }
}


SmsService smsService = SmsFactory.produceSms();
smsService.send("187581367762","hello world");

看到这动态代理,又很容易想到AOP。而AOP也就是真的动态代理,并不是装饰器代码方式。

总结

代理模式为了屏蔽被代理对象被外部访问,但操作还是被代理对象在操作。

而动态代理的核心是反射

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值