图22. Spring 中使用代理模式的结构图
$Proxy就是创建的代理对象,而Subject是抽象主题,代理对象是通过InvocationHandler来持有对目标对象的引用的。
2. 策略模式
2.1 策略模式原理
策略模式顾名思义就是做某事的策略,这在编程上是指完成某个操作通常有多种方法,这些方法各有千秋,可能有不能的使用场合,然而这些操作方法都有可能用到。每一个操作方法都当做一个实现策略,使用者可以根据需要选择合适的策略。
下面是策略模式的结构:
图23. 策略模式的结构
?
Context:使用不同策略的环境,它可以根据自身的条件选择不同的策略实现类来完成所要的操作,它持有一个Strategy实例的引用。创建具体策略的方法也可以由他完成 ? ?
Strategy:抽象策略,定义每个策略都要实现的方法
ConcreteStrategy:具体策略实现类,实现抽象策略中定义的策略方法
2.2 Spring中策略模式的实现
Spring中有很多地方使用策略模式,如Bean定义对象的创建以及代理对象的创建等,这里主要看下代理对象的创建的策略模式的实现。
前面已经了解了Spring的代理方式有两种:JDK动态代理和CGLIB代理。这两个代理方式的使用正是使用了策略模式,它的结构如下图所示:
图24. Spring中策略模式结构图
上图与标准的策略模式稍有不同,这里抽象策略是AopProxy接口,Cglib2AopProxy和
JdkDynamicAopProxy分别代表两种策略的实现方式,ProxyFactoryBean就是代表Context角色,它根据条件选择使用JDK代理还是CGLIB代理。而另外三个类主要是负责创建具体策略对象,ProxyFactoryBean是通过依赖方法来关联具体策略对象的,它是通过调用策略对象的getProxy(ClassLoader classLoader)来完成具体操作的。
四、 Webx2.0与Spring3.0框架的比较
Webx主要作为表现层框架与Spring主要用于业务逻辑层,本身可比性不强。
Webx也有一个容器叫Service容器,可以说Webx也是基于这个容器工作的。Webx的Service容器和Spring的IOC容器有很多相似之处,一个Service组件相当于Spring中的Bean,Service的管理是通过ServiceManager,而Spring是BeanFactory,Spring中的ApplicationContext相当于Webx中的WebxController。虽然结构有点类似,但实际差别很大。
首先Webx没有把容器的构建者和容器的使用者角色分开,在Webx中Service是兼顾两个角色的,它既是容器的执行者又是容器的被执行者。但Spring不同,我们使用Spring主要是用来管理我们自己定义的对象间的关系。虽然Spring本身的执行也是基于同样的原理,但Spring并没有把容器执行者角色需要的类交给用户去配置,Spring把它作为默认配置向用户屏蔽。虽然Webx中也有默认的Service配置,但是用户仍然可以修改容器本身的结构行为。
其次,Webx的耦合性太强,我在《Webx框架的系统架构与设计模式》中曾经把Webx中的Service划分为三层,其中一层就是说到Service之间是批次依赖的,框架之间有依赖关系不可避免。但
这种依赖是不是要扩展到框架之外,让用户也绑定到框架上就值得考虑了。Webx中就有这样的,本来Webx把对Service的配置开放给用户,是想提高其扩展性。但是有一个缺点就是,你要配置的这些Service他们有彼此之间依赖,而这种依赖是紧耦合的。也就是Service之间的调用时写在Service中某个方法中的,虽然Service对象的创建是通过ServiceManager来完成的,但是调用其他Service这种关系还是写死的,也就是,Service之间的关联关系并不是由使用者通过配置文件就能完全管理的。这种通过把框架本身的执行逻辑交给框架使用者来控制而达到其框架本身的扩展性,是非常不可取的。而Spring做的非常好。框架本身的执行与使用者的代码没有太强的耦合性,也就是你不能控制框架本身的执行逻辑,你能控制改变的只能是你自己定义的行为,当然你可以借助Spring让他更强大。
再次,Webx扩展性不好,我至今仍然想不通Webx为何要构建四个容器,Webx中有个Spring,Spring中有个Webx。唯一的解释就是Webx不能与Spring有很好的互通性。也就是Webx要访问Spring怎么办呢?就在Webx中起一个Spring容器,那Spring要访问Webx又怎么办呢?Spring中起一个Webx容器。前面的Webx又要访问后面的Spring咋办。只能让前面的Spring指向后面的Spring,这关系真复杂。为何有这么复杂的关系,唯一的解释只能是没有良好的扩展点。到底是Spring没有还是Webx没有?