浅谈设计模式之代理模式(proxy)
Posted ZzQ的鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈设计模式之代理模式(proxy)相关的知识,希望对你有一定的参考价值。
一、定义
为这个对象提供一种代理以达到控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象[业务场景],而代理对象可以在客户端和目标对象之间起到中介的作用。
二、特征
代理类与委托类有同样的接口。(用JAVA的语言来说就是有实现同样的接口)
代理模式结构图(图片来自《大话设计模式》)
三、静态代理&动态代理
1)、静态代理
指在编译阶段就已经明确创建指定了接口、代理对象的被代理对象,主要是代理对象的明确建立,固定【静态代理】被代理对象。
2)动态代理
指在运行阶段动态创建代理对象,代理对象运行期间动态变化。
相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。
四、通俗案例
静态代理:
经纪人有一个唱歌的行为(接口),摇滚歌手A会唱摇滚的歌,歌迷有想听歌摇滚的歌直接找歌手来唱,这样看起来经纪人好像没什么用;有一天经纪人跟摇滚歌手签合同,摇滚歌手要唱歌只能通过经纪人同意才行,那么歌迷想听摇滚歌手唱歌的时候只能通过经纪人渠道来听歌了,而经纪人要收门票费用,那么这个过程就是静态代理,收取费用就是代理的作用(功能)了;静态就是经纪人只有摇滚歌手A,没办法改其他人了
动态代理:
在静态的基础之上,流行歌手B会唱流行歌曲歌迷,那么同一个经纪人就要跟流行歌手继续签合同,歌迷想听流行歌手还是一样要找经纪人,经纪人一样还是要收门票费用,但是这个似乎还经纪人就变成一个动态代理经纪人了,歌迷想听什么歌都可以了。
经纪人=代理类
歌手=被代理类
收取额外费用=功能
总结:静态代理(1:1)可以简单理解成动态代理(1:N)的进一步抽象
五、代码范例
静态代理:
/**
* 歌手接口
*/
public interface SingerInterface {
//唱歌方法
void singing();
}
/**
* 摇滚歌手
*/
public class RockSingerService implements SingerInterface{
public void singing(){
System.out.println("我是摇滚歌手,开始唱歌");
}
}
/**
* 经纪人
*/
public class SingerProxyService implements SingerInterface{
private RockSingerService rockSingerService;
public void singing(){
System.out.println("摇滚歌手已经跟我签约了,我是代理,我要收门票");
rockSingerService.singing();
System.out.println("摇滚歌手已经唱完歌了,我赚钱了我要送福利给歌迷,哈哈哈");
}
public RockSingerService getRockSingerService() {
return rockSingerService;
}
public void setRockSingerService(RockSingerService rockSingerService) {
this.rockSingerService = rockSingerService;
}
}
/**
* 点唱
*/
public class Main {
public static void main(String[] args) {
//创建一个摇滚歌手
RockSingerService rockSingerService = new RockSingerService();
//创建一个经纪人
SingerProxyService singerProxyService = new SingerProxyService();
//签约
singerProxyService.setRockSingerService(rockSingerService);
//粉丝向经纪人要求摇滚歌手唱歌
singerProxyService.singing();
}
}
输出:
摇滚歌手已经跟我签约了,我是代理,我要收门票
我是摇滚歌手,开始唱歌
摇滚歌手已经唱完歌了,我赚钱了我要送福利给歌迷,哈哈哈
动态代理:
实现动态代理有多种方式,我就在上面的基础上用java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象
/**
* 经典歌手
*/
public class ClassesSingerService implements SingerInterface{
public void singing(){
System.out.println("我是经典歌手,开始唱歌");
}
}
public class DynamicMain {
public static void main(String[] args) {
//创建摇滚歌手
//点名要经典歌手唱歌
RockSingerService rockSingerService = new RockSingerService();
//创建动态代理模板类
DynamicProxyService dynamicProxyService = new DynamicProxyService();
dynamicProxyService.setProxyObject(rockSingerService);
//通过反射生成具体摇滚歌手代理类->Proxy
SingerInterface rockSinger = (SingerInterface)Proxy.newProxyInstance(
dynamicProxyService.getClass().getClassLoader(),
rockSingerService.getClass().getInterfaces()
,dynamicProxyService);
//唱歌
rockSinger.singing();
System.out.println("=====================================================");
//点名要经典歌手唱歌
ClassesSingerService classesSingerService = new ClassesSingerService();
dynamicProxyService.setProxyObject(classesSingerService);
SingerInterface classesSinger = (SingerInterface)Proxy.newProxyInstance(
dynamicProxyService.getClass().getClassLoader(),
classesSingerService.getClass().getInterfaces()
,dynamicProxyService);
//唱歌
classesSinger.singing();
}
}
输出:
com.sun.proxy.$Proxy0已经跟我签约了,我是代理,我要收门票
我是摇滚歌手,开始唱歌
com.sun.proxy.$Proxy0已经唱完歌了,我赚钱了我要送福利给歌迷,哈哈哈
=====================================================
com.sun.proxy.$Proxy0已经跟我签约了,我是代理,我要收门票
我是经典歌手,开始唱歌
com.sun.proxy.$Proxy0已经唱完歌了,我赚钱了我要送福利给歌迷,哈哈哈
以上是个人学习总结,如说的不对,欢迎给以指出,谢谢!
以上是关于浅谈设计模式之代理模式(proxy)的主要内容,如果未能解决你的问题,请参考以下文章