1、代理模式
-
定义:为其他对象提供一种代理以控制(隔离使用接口)对这个对象的访问等。
-
动机
- 在面向对象系统中,有些对象由于某种原因(比如对象需要进程外的访问等,例如在分布式的系统中),直接访问会给使用者或系统结构带来很多麻烦。
- 如何在不失去透明操作(无感知)对象的同时来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的一种解决方式。
-
个人理解:
- 代理模式在一些例如AOP编程中大量的使用动态代理模式
- AOP概念:面向切面编程,英文全称Aspect Oriented Programming;AOP是OOP编程的延伸,也是软件开发中的一个热点,也是Java语言Spring框架中的一个重要组成部分,是函数式编程的一种衍生范型。
- AOP作用:利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
- AOP原理:AOP底层是通过动态代理(接口代理、Cglib代理)。通过动态代理可以在程序运行的时候针对某些功能进行逻辑层面的增强,从而达到在不修改源代码的情况下能够使得某些方法功能加强,当不需要增强时直接去掉代理,也不用修改源代码!总之:AOP的作用就是解耦!
2、案例分析
2.1、基础实现
class ISubject{
public:virtual void process() = 0;
};
class RealSubject: public ISubject{
public:virtual void process() override{// .....}
};
class ClientApplication{
private:ISubject *subject;
public:ClientApplication(ISubject *iSubject): subject(iSubject){}void DoTask(){subject->process();}
};
- 假设现在有一个ISubject的接口和一个实现子类、在ClientApplication类中需要依赖这个接口和子类、很朴素的做法就是在通过注入的方式加入进来,也可以通过工厂方法等方式搞一个ISubject的子类么。
- 但其实这种做法包括工厂等都有一个大前提条件,就是依赖的这个ISubject的接口、子类与当前需要使用的类ClientApplication接口在同一个进程中或者同一个项目下,这样就能保证加载到么。
2.1、代理模式
-
而如果在一些分布式系统中,不同项目之间通常有一些接口功能的调用请求,通过一些手段加载到当前项目中。
-
这种调用等一些操作都会通过RPC或者GRPC一些远程调用的方式来加载这个对象,此时这种直接注入的方式就无效了。
-
这时候代理模式就体现出它的作用了,通过加上代理层代理所需对象的功能,所需对象的加载在这里完成并且调用,对外暴露接口让ClientApplication调用。
-
这样做的好处是:
- 首先是透明的:ClientApplication对这个只管使用并不关心它怎么来的
- 其次是高内聚低耦合:代理的过程放到一个方法中,而不融入到调用的地方。这样就功能高度内聚,接口之间低耦合。
class ISubject{
public:virtual void process() = 0;
};
class SubjectProxy: public ISubject{
public:virtual void process() override{/** 对RealSubject的一种间接访问* 这其中伴随着很复杂的一些过程* 总之这里可能会获取到一个RealSubject的对象*/RealSubject realSubject = ....;realSubject.process();}
};
class ClientApplication{
private:ISubject *subject;
public:ClientApplication(ISubject *proxySubject): subject(proxySubject){}void DoTask(){subject->process();}
};
3、总结
-
“增加一层”是软件系统重对许多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段。
-
具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy(例如aop)
-
Proxy并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损失一些透明性也是可以接受的。