马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
署理模式(Proxy Pattern)
概念
署理模式(Proxy Pattern)是一种结构型操持模式,署理对象在不改变目的对象功能的条件下,通过控制对目的对象的访问,来实现耽误加载、权限控制、日志 纪录等功能。署理模式可以通过提供一个中介对象,来控制客户端和实际目的对象之间的交互。
应用场景
- 长途署理(Remote Proxy):为位于差别地点空间的对象提供署理,办理长途调用题目。典范的例子是RMI(Remote Method Invocation),通过署理对象举行长途方法调用。
- 假造署理(Virtual Proxy):为某些须要较高开销的对象提供署理,耽误其加载和创建。好比,大型图片或文档的加载可以通过假造署理来举行,只有认真正须要时才创建实际对象。
- 掩护署理(Protection Proxy):用于控制对对象的访问权限。署理对象查抄调用者是否具有访问权限,只有在权限答应时,才华访问目的对象。
- 智能引用署理(Smart Reference Proxy):在访问对象时参加一些附加操纵,如统计实际对象的引用次数、纪录日志
、查抄锁等。
- 缓存署理(Caching Proxy):署理可以缓存某些盘算结果或操纵结果,使得后续的雷同哀求不须要重复盘算,提拔体系性能。
留意点
- 署理类和实际类必须实现雷同的接口:署理类的操持应与目的类保持划一,使得客户端在利用署理类时与利用实际类没有差别。
- 性能开销:只管署理模式可以增长功能,但也大概增长体系开销,尤其是长途署理涉及到网络传输时。
- 恰当复杂的控制场景:署理模式尤其恰当在须要控制访问、管理复杂操纵、或添加额外处理处罚逻辑的场景中利用。
焦点要素
- Subject(抽象主题脚色):界说署理类和目的类的共同接口,使得署理类和目的类可以被客户端通过雷同的方式调用。
- RealSubject(真实主题脚色):界说目的对象,实现真实的业务逻辑。
- Proxy(署理脚色):负责控制对真实主题对象的访问,通常会引用一个真实主题对象,并通过实现抽象主题接口来署理其操纵。
Java代码完备示例
代码示例:静态署理- // 抽象接口,定义真实主题和代理共同的行为
- interface Subject {
- void request();
- }
- // 真实主题,实现实际的业务逻辑
- class RealSubject implements Subject {
- @Override
- public void request() {
- System.out.println("真实主题执行请求");
- }
- }
- // 代理类,控制对真实主题的访问
- class Proxy implements Subject {
- private RealSubject realSubject;
- @Override
- public void request() {
- // 代理可以在调用真实对象之前执行一些额外操作
- if (realSubject == null) {
- realSubject = new RealSubject();
- }
- System.out.println("代理:在调用真实对象前的额外操作");
- realSubject.request();
- System.out.println("代理:在调用真实对象后的额外操作");
- }
- }
- // 客户端
- public class Client {
- public static void main(String[] args) {
- Subject proxy = new Proxy();
- proxy.request();
- }
- }
复制代码 输出结果:- 代理:在调用真实对象前的额外操作
- 真实主题执行请求
- 代理:在调用真实对象后的额外操作
复制代码 各种变形用法完备示例
- 假造署理(Virtual Proxy)
假造署理的重要目的是推迟大开销对象的创建,直到须要利用时才创建。典范例子是耽误加载大型图片或文档。
代码示例:- interface Image {
- void display();
- }
- // 真实的图像类,实际加载图片
- class RealImage implements Image {
- private String fileName;
- public RealImage(String fileName) {
- this.fileName = fileName;
- loadFromDisk();
- }
- private void loadFromDisk() {
- System.out.println("加载图片: " + fileName);
- }
- @Override
- public void display() {
- System.out.println("显示图片: " + fileName);
- }
- }
- // 虚拟代理类
- class ProxyImage implements Image {
- private RealImage realImage;
- private String fileName;
- public ProxyImage(String fileName) {
- this.fileName = fileName;
- }
- @Override
- public void display() {
- if (realImage == null) {
- realImage = new RealImage(fileName);
- }
- realImage.display();
- }
- }
- // 客户端
- public class VirtualProxyClient {
- public static void main(String[] args) {
- Image image = new ProxyImage("test.jpg");
- // 图片首次显示时加载
- image.display();
- System.out.println("");
- // 第二次调用时不需要加载
- image.display();
- }
- }
复制代码 输出结果:- 加载图片: test.jpg
- 显示图片: test.jpg
- 显示图片: test.jpg
复制代码 - 动态署理(Dynamic Proxy)
动态署理是在运行时创建署理类,而不是在编译时创建。在Java中,可以利用java.lang.reflect.Proxy类来实现动态署理,署理类可以动态署理接口界说的全部方法。
代码示例:- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- // 定义抽象接口
- interface Service {
- void operation();
- }
- // 实现接口的真实类
- class RealService implements Service {
- @Override
- public void operation() {
- System.out.println("执行实际操作");
- }
- }
- // 动态代理处理器
- class DynamicProxyHandler implements InvocationHandler {
- private Object target;
- public DynamicProxyHandler(Object target) {
- this.target = target;
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- System.out.println("动态代理:在方法执行前");
- Object result = method.invoke(target, args);
- System.out.println("动态代理:在方法执行后");
- return result;
- }
- }
- // 客户端
- public class DynamicProxyClient {
- public static void main(String[] args) {
- RealService realService = new RealService();
- Service proxyInstance = (Service) Proxy.newProxyInstance(
- realService.getClass().getClassLoader(),
- realService.getClass().getInterfaces(),
- new DynamicProxyHandler(realService)
- );
- proxyInstance.operation();
- }
- }
复制代码 输出结果:- 动态代理:在方法执行前
- 执行实际操作
- 动态代理:在方法执行后
复制代码 - 掩护署理(Protection Proxy)
掩护署理用于控制访问权限,可以通过署理来查抄调用者是否具备权限,只有在通过查抄时,才华调用目的对象的方法。
代码示例:- interface BankAccount {
- void deposit(double amount);
- void withdraw(double amount);
- }
- class RealBankAccount implements BankAccount {
- private double balance;
- public RealBankAccount(double balance) {
- this.balance = balance;
- }
- @Override
- public void deposit(double amount) {
- balance += amount;
- System.out.println("存款成功,当前余额: " + balance);
- }
- @Override
- public void withdraw(double amount) {
- if (balance >= amount) {
- balance -= amount;
- System.out.println("取款成功,当前余额: " + balance);
- } else {
- System.out.println("余额不足,取款失败");
- }
- }
- }
- // 保护代理类
- class ProtectionProxy implements BankAccount {
- private RealBankAccount realBankAccount;
- private String userRole;
- public ProtectionProxy(String userRole, double initialBalance) {
- this.userRole = userRole;
- realBankAccount = new RealBankAccount(initialBalance);
- }
- @Override
- public void deposit(double amount) {
- realBankAccount.deposit(amount);
- }
- @Override
- public void withdraw(double amount) {
- if ("ADMIN".equals(userRole)) {
- realBankAccount.withdraw(amount);
- } else {
- System.out.println("无权限取款");
- }
- }
- }
- // 客户端
- public class ProtectionProxyClient {
- public static void main(String[] args) {
- BankAccount adminAccount = new ProtectionProxy("ADMIN", 1000);
- adminAccount.withdraw(500);
- BankAccount userAccount = new ProtectionProxy("USER", 1000);
- userAccount.withdraw(500);
- }
- }
复制代码 输出结果:
总结
署理模式通过引入署理类为目的对象提供额外的功能或控制。它实用于耽误加载、权限控制、日志 纪录、长途调用等场景。署理模式可以分为静态署理和动态署理,而且具有多种变体,如假造署理、掩护署理、长途署理等。
|