IoC食谱-图案

Tapestry IoC支持实现四人组设计模式事实上,IoC容器本身是工厂模式的升级版本。

相关文章

这些模式的基础通常是使用服务构建器方法,其中配置因为服务与工厂相结合,动态生成服务实现。

指挥链模式

主要文章:指挥系统

让我们再次从Tapestry代码库来看另一个示例。这个注入提供者接口用于处理Tapestry页面或组件字段上的@Inject注释。许多不同的实例组合在一起,形成一个指挥系统.

该接口只有一个方法(这绝非罕见):

公共接口InjectionProvider{布尔provideInjection(String fieldName,Class fieldType,ObjectLocator locator,类转换转换,可变组件模型组件模型);}

返回类型指示提供程序是否能够执行某些操作。例如,AssetInjectionProvider检查字段上是否有@Path注释,如果有,则将路径转换为资产,与ClassTransformation对象一起实现注入,并返回true以指示成功。返回true会提前终止链,并且该真值最终会返回给调用方。

在其他情况下,它返回false,命令链继续向下传递到下一个提供程序。如果没有提供程序能够处理注入,那么最终会返回值false。

InjectionProvider服务是通过捐款建立的。以下是TapestryModule的贡献:

公共静态void contributeInjectionProvider(OrderedConfiguration<InjectionProvider>配置,MasterObjectProvider主对象提供程序,ObjectLocator定位器,符号源符号源,资产源资产源){configuration.add(“Default”,新的DefaultInjectionProvider(masterObjectProvider,locator));configuration.add(“ComponentResources”,新ComponentResourcesInjectionProvider());configuration.add(“CommonResources”,new CommonResoicesInjectionProvider(),“after:Default”);configuration.add(“资产”,new AssetInjectionProvider(symbolSource,assetSource),before:Default”);configuration.add(“Block”,new BlockInjectionProvider(),“before:Default”);configuration.add(“Service”,new ServiceInjectionProvider(locator),“after:*”);}

当然,也可以在其他模块中做出其他贡献。。。如果你想加入你自己的注射方式。

配置通过服务构建器方法转换为服务:

公共InjectionProvider构建(List<InjectionProvider>configuration,ChainBuilder ChainBuilder){return chainBuilder.build(InjectionProvider.class,configuration);}

现在,让我们看看这是如何使用的。InjectWorker类使用InjectAnnotation查找字段,并使用命令链注入适当的值。然而,对于注射工人来说,没有链条。。。只是一个单一的对象,该对象实现了InjectionProvider接口。

公共类InjectWorker实现ComponentClassTransformWorker{私有最终ObjectLocator定位器;//真的,一系列的命令私有最终注入提供者注入提供者;public InjectWorker(ObjectLocator locator,InjectionProvider injectionProvisor){this.locator=定位器;this.injectionProvider=注入提供者;}公共最终void转换(ClassTransformation转换,MutableComponentModel模型){for(String fieldName:transformation.findFieldsWithAnnotation(Inject.class)){注入注释=transformation.getFieldAnnotation(fieldName,Inject.class);尝试{String fieldType=转换.getFieldType(fieldName);类类型=transformation.toClass(fieldType);布尔成功=injectionProvider.provideInjection(字段名称,类型,定位器,转化,模型);if(success)transformation.claimField(fieldName,annotation);}catch(RuntimeException ex){抛出新的RuntimeException(ServicesMessages.fieldInjectionError(转换.getClassName(),fieldName,ex),ex);}}}}

将链简化为单个对象大大简化了代码:我们已经已考虑因素命令链中隐含的循环。这样就消除了大量代码,测试的代码更少,通过InjectWorker的路径更少,从而进一步降低了其复杂性。我们不必测试注入提供程序列表为空、或仅由单个对象组成、或是其中第三个返回true的对象的情况:它看起来像单个对象,行为也像单个对象。。。但它的实现使用了许多对象。