Java常用设计模式--代理模式(Proxy Pattern)
时间:2022-07-23
本文章向大家介绍Java常用设计模式--代理模式(Proxy Pattern),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象。代理模式(Proxy Pattern)属于结构型模式。
代理模式中的角色
- 抽象对象角色(AbstractObject):声明了目标对象和代理对象的共同接口,这样依赖在任何可以使用目标对象的地方都可以使用代理对象。
- 目标对象角色(RealObject):定义了代理对象所代表的目标对象。
- 代理对象角色(ProxyObject):代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象。代理对象通常在客户端调用传递给目标对象之前或者之后,执行某个操作,而不是单纯的将调用传递给目标对象。
举个例子:
你想喝奶茶,但是你不想自己去奶茶店买,而是找了外卖小哥送,这就是代理模式
静态代理
package com.example.proxy;
/**
* 抽象对象角色 奶茶
*/
public interface BuyMilkyTea {
void buyMilkyTea();
}
package com.example.proxy;
/**
* 目标对象角色 我
*/
public class MyPeople implements BuyMilkyTea {
@Override
public void buyMilkyTea() {
System.out.println("我拿到奶茶");
}
}
package com.example.proxy;
/**
* 代理对象角色 外卖小哥
*/
public class TakeOutPeople implements BuyMilkyTea {
private BuyMilkyTea buyMilkyTea;
public TakeOutPeople(BuyMilkyTea buyMilkyTea) {
this.buyMilkyTea = buyMilkyTea;
}
@Override
public void buyMilkyTea() {
System.out.println("配送前操作,取奶茶");
buyMilkyTea.buyMilkyTea();
System.out.println("配送后操作,确认送达");
}
}
package com.example.proxy;
public class Test {
public static void main(String[] args) {
MyPeople myPeople = new MyPeople();
TakeOutPeople takeOutPeople = new TakeOutPeople(myPeople);
takeOutPeople.buyMilkyTea();
}
}
缺点: 代理类和委托类实现相同的接口,同时要实现相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
动态代理
动态代理有别于静态代理,是根据代理的对象,动态创建代理类。这样,就可以避免静态代理中代理类接口过多的问题。动态代理是实现方式,是通过反射来实现的,借助Java自带的java.lang.reflect.Proxy
,通过固定的规则生成。
其步骤如下:
- 编写一个委托类的接口,即静态代理的抽象对象角色(AbstractObject)
- 实现一个真正的委托类,即静态代理的目标对象角色(RealObject):
- 创建一个动态代理类,实现
InvocationHandler
接口,并重写该invoke
方法 - 在测试类中,生成动态代理的对象。
package com.example.dynamicproxy;
/**
* 抽象对象角色 奶茶
*/
public interface BuyMilkyTea {
void buyMilkyTea();
}
package com.example.dynamicproxy;
/**
* 目标对象角色 我
*/
public class MyPeople implements BuyMilkyTea {
@Override
public void buyMilkyTea() {
System.out.println("我拿到奶茶");
}
}
package com.example.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 动态代理类
*/
public class DynamicTakeOutPeople implements InvocationHandler {
private Object object;
public DynamicTakeOutPeople(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(object, args);
return invoke;
}
}
package com.example.dynamicproxy;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
MyPeople myPeople = new MyPeople();
DynamicTakeOutPeople dynamicTakeOutPeople = new DynamicTakeOutPeople(myPeople);
ClassLoader classLoader = dynamicTakeOutPeople.getClass().getClassLoader();
BuyMilkyTea buyMilkyTea = (BuyMilkyTea)Proxy.newProxyInstance(classLoader, new Class[]{BuyMilkyTea.class}, dynamicTakeOutPeople);
buyMilkyTea.buyMilkyTea();
}
}
- 【LeetCode 500】关关的刷题日记27 Keyboard Row
- 1601: [Usaco2008 Oct]灌水
- 1657: [Usaco2006 Mar]Mooo 奶牛的歌声
- 1610: [Usaco2008 Feb]Line连线游戏
- 1012: [JSOI2008]最大数maxnumber
- 1430: 小猴打架
- 1202: [HNOI2005]狡猾的商人
- 1059: [ZJOI2007]矩阵游戏
- 3039: 玉蟾宫
- 大公司都有哪些开源项目之腾讯
- Vue拖拽组件开发实例
- 一小时培训之神经网络入门
- 【LeetCode 290】 关关的刷题日记28 Word Pattern
- Redis知识点速查
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Python数据科学:神经网络
- 火箭五年四遇勇士,终究还是败了。
- 谁才是权游的真正主角。
- Java8 Stream流的终端操作
- Python 爬取王者农药全套皮肤
- 时间都去哪儿了--python性能优化
- Python干货 | 遥感影像拼接
- Java8 Stream 创建流
- Java8 Stream 基本类型特化流
- Java8 Stream 自定义收集器Collector
- 收藏|Flink比Spark好在哪?
- SpringCloud Config 分布式配置
- 经过一年的煎熬,我们还是决定把系统升级成基于 Spring Cloud 的微服务架构
- OpenCV:人脸检测。
- 如何设计缓存系统:缓存穿透,缓存击穿,缓存雪崩解决方案分析