嘉兴网站建设科技有限公司,合肥房产备案网,哪家企业网页制作好,安卓网站开发在软件开发中#xff0c;我们经常需要控制对某些对象的访问——可能是为了延迟加载、添加额外功能或保护敏感资源。这正是代理模式大显身手的地方。作为结构型设计模式的重要成员#xff0c;代理模式在众多知名框架和系统中扮演着关键角色。本文将全面剖析代理模式的方方面面…
在软件开发中我们经常需要控制对某些对象的访问——可能是为了延迟加载、添加额外功能或保护敏感资源。这正是代理模式大显身手的地方。作为结构型设计模式的重要成员代理模式在众多知名框架和系统中扮演着关键角色。本文将全面剖析代理模式的方方面面带你领略这一模式的精妙之处。
一、代理模式概述1.1 什么是代理模式代理模式Proxy Pattern是一种结构型设计模式它为其他对象提供一种代理以控制对这个对象的访问。简单来说代理就是一个替身它代表另一个对象即真实对象执行某些操作同时可以在访问真实对象前后添加自己的逻辑。1.2 代理模式的核心思想代理模式的核心在于控制访问它遵循了面向对象设计原则中的单一职责原则和开闭原则单一职责真实对象只需关注核心业务逻辑而访问控制、日志记录等职责交给代理开闭原则可以在不修改真实对象代码的情况下通过代理扩展功能1.3 生活中的代理类比现实生活中代理的例子比比皆是房屋中介代理房东处理租房事宜明星经纪人代理明星安排演出和商业活动信用卡代理银行账户进行支付这些代理的共同特点是它们都代表另一个实体执行操作同时可以添加自己的处理逻辑如中介收取佣金、经纪人筛选邀约等。二、代理模式的结构与实现2.1 UML类图2.2 核心角色Subject抽象主题定义真实主题和代理主题的共同接口可以是接口或抽象类RealSubject真实主题实现真实业务逻辑的类是被代理的对象Proxy代理包含对真实主题的引用实现与真实主题相同的接口可以控制对真实主题的访问2.3 Java实现示例
// 抽象主题
interface Database {void query(String sql);
}// 真实主题
class RealDatabase implements Database {Overridepublic void query(String sql) {System.out.println(执行查询: sql);// 实际数据库操作...}
}// 代理
class DatabaseProxy implements Database {private RealDatabase realDatabase;private ListString blacklist Arrays.asList(DELETE, DROP, TRUNCATE);Overridepublic void query(String sql) {// 安全检查if (containsBlacklistedKeywords(sql)) {throw new RuntimeException(查询包含危险操作);}// 日志记录System.out.println([ LocalDateTime.now() ] 执行查询: sql);// 延迟初始化if (realDatabase null) {realDatabase new RealDatabase();}// 执行实际查询realDatabase.query(sql);// 后置处理System.out.println(查询完成);}private boolean containsBlacklistedKeywords(String sql) {return blacklist.stream().anyMatch(sql::contains);}
}// 客户端代码
public class Client {public static void main(String[] args) {Database database new DatabaseProxy();database.query(SELECT * FROM users); // 正常执行database.query(DROP TABLE users); // 抛出异常}
}这个示例展示了一个数据库查询代理它实现了安全检查保护代理日志记录智能引用代理延迟初始化虚拟代理三、代理模式的类型3.1 远程代理Remote Proxy特点为位于不同地址空间的对象提供本地代表应用场景RPC远程过程调用Web服务客户端分布式系统中的存根Stub示例
// 远程服务接口
interface WeatherService {String getWeather(String city);
}// 本地代理
class WeatherServiceProxy implements WeatherService {Overridepublic String getWeather(String city) {// 通过网络调用远程服务return callRemoteWeatherService(city);}private String callRemoteWeatherService(String city) {// 实际网络通信逻辑...return Sunny;}
}3.2 虚拟代理Virtual Proxy特点根据需要创建开销很大的对象应用场景大图加载复杂对象初始化资源密集型操作示例
class HighResolutionImage implements Image {public HighResolutionImage(String path) {loadImage(path); // 耗时操作}private void loadImage(String path) {// 加载大图...}
}class ImageProxy implements Image {private String path;private HighResolutionImage realImage;public ImageProxy(String path) {this.path path;}Overridepublic void show() {if (realImage null) {realImage new HighResolutionImage(path); // 延迟加载}realImage.show();}
}3.3 保护代理Protection Proxy特点控制对原始对象的访问权限应用场景权限控制敏感操作保护访问限制示例
interface BankAccount {void withdraw(double amount);double getBalance();
}class RealBankAccount implements BankAccount {private double balance;Overridepublic void withdraw(double amount) {balance - amount;}Overridepublic double getBalance() {return balance;}
}class BankAccountProxy implements BankAccount {private RealBankAccount account;private User user;public BankAccountProxy(User user) {this.user user;this.account new RealBankAccount();}Overridepublic void withdraw(double amount) {if (user.hasPermission(WITHDRAW)) {account.withdraw(amount);} else {throw new SecurityException(无取款权限);}}Overridepublic double getBalance() {if (user.hasPermission(VIEW_BALANCE)) {return account.getBalance();} else {throw new SecurityException(无查看余额权限);}}
}3.4 智能引用代理Smart Reference Proxy特点在访问对象时执行附加操作应用场景引用计数对象池管理缓存机制示例
class ExpensiveObject {void process() {System.out.println(处理中...);}
}class SmartProxy {private ExpensiveObject realObject;private int accessCount 0;public void process() {if (realObject null) {realObject new ExpensiveObject();}accessCount;System.out.println(访问次数: accessCount);realObject.process();if (accessCount 5) {System.out.println(重置对象...);realObject null;accessCount 0;}}
}四、代理模式的深入应用4.1 Spring框架中的代理Spring框架广泛使用代理模式主要体现在AOP面向切面编程Spring AOP使用JDK动态代理或CGLIB代理实现为业务组件添加事务管理、日志记录等横切关注点事务管理Transactional注解背后的代理机制在方法调用前后管理事务边界Configuration类配置类的代理确保Bean方法单例性示例
Service
public class UserService {Transactionalpublic void createUser(User user) {// 数据库操作}
}// Spring在运行时创建代理类
class UserServiceProxy extends UserService {private UserService target;private PlatformTransactionManager txManager;Overridepublic void createUser(User user) {TransactionStatus status txManager.getTransaction(new DefaultTransactionDefinition());try {target.createUser(user);txManager.commit(status);} catch (Exception e) {txManager.rollback(status);throw e;}}
}4.2 MyBatis中的代理MyBatis使用JDK动态代理实现Mapper接口
public interface UserMapper {Select(SELECT * FROM users WHERE id #{id})User getUserById(int id);
}// MyBatis在运行时生成代理实现
class MapperProxy implements InvocationHandler {private SqlSession sqlSession;Overridepublic Object invoke(Object proxy, Method method, Object[] args) {// 解析注解中的SQLString sql method.getAnnotation(Select.class).value();// 执行SQL并返回结果return sqlSession.selectOne(sql, args[0]);}
}4.3 RPC框架中的代理远程方法调用RPC框架如Dubbo、gRPC都使用代理模式
// 服务接口
public interface OrderService {Order getOrder(long id);
}// 客户端代理
class OrderServiceProxy implements OrderService {private String serviceUrl;Overridepublic Order getOrder(long id) {// 序列化参数byte[] request serialize(id);// 网络调用byte[] response sendRequest(serviceUrl, request);// 反序列化结果return deserialize(response);}
}五、代理模式的优缺点5.1 优点职责分离代理对象处理非功能性需求如安全、日志真实对象专注业务逻辑开闭原则无需修改真实对象即可扩展功能访问控制代理可以控制对真实对象的访问性能优化虚拟代理可以实现延迟加载提高系统响应速度5.2 缺点复杂度增加引入代理层会增加系统复杂度性能开销代理调用会带来额外的处理时间间接性可能使调试变得困难因为调用栈更深六、代理模式与相关模式的比较6.1 代理模式 vs 装饰器模式对比维度代理模式装饰器模式目的控制访问增强功能关系代理知道被代理对象的生命周期装饰器与被装饰对象独立关注点访问机制如延迟加载、权限控制添加新行为6.2 代理模式 vs 适配器模式对比维度代理模式适配器模式接口保持相同接口转换不同接口目的控制访问解决接口不兼容问题使用时机设计阶段规划后期集成时使用七、实际应用建议何时使用代理模式需要延迟初始化虚拟代理需要控制资源访问保护代理需要添加横切关注点AOP需要远程调用远程代理实现选择静态代理代理类在编译时确定适合简单场景动态代理运行时生成代理类更灵活JDK动态代理、CGLIB性能考虑对于频繁调用的方法注意代理带来的性能开销考虑使用轻量级代理或直接访问设计原则遵循最少知识原则代理不应暴露过多真实对象细节保持代理接口简洁避免成为上帝对象结语代理模式作为设计模式家族中的重要成员其应用范围从简单的对象访问控制到复杂的框架实现无处不在。理解并掌握代理模式不仅能帮助我们设计出更加灵活、安全的系统还能深入理解众多流行框架的内部工作机制。无论是日常开发中的权限控制、日志记录还是分布式系统中的远程调用代理模式都展现出其强大的适应性和生命力。希望本文能为你打开代理模式的大门助你在软件设计之路上更进一步。