本篇介绍企业应用架构的基本模式之一插件(Plugin)模式。
插件(Plugin)
在配置时而非编译时连接类。
背景
当应用程序代码需要在多个环境运行,且每个环境对特定行为需要不同的实现时,通常会使用分离接口模式。大多数开发通过编写一个工厂方法来在不同的环境下生成相应的实现。假定通过分离接口来定义你的主键生成器,以便你可以使用一个简单的内存计数器来进行单元测试,而在真实环境由数据库管理的序列。你的工厂方法很可能包含一条判断语句,这一语句检查一个局部环境变量以确定系统是否处于测试模式,并返回正确的结果。当你有数个工厂以后,你的手头会变得一团糟。建立一个新的部署配置需要在多个工厂中修改条件语句,然后重新编译和部署。配置工作不应当如此分散在整个应用程序当中,也不应当重新编译和部署。插件模式通过集中化的、运行时配置的方法解决了这些问题。
做法
首先要做的是通过分离接口定义所有那些在不同运行环境下有不同实现的行为。除此之外,我们还使用基本的工厂模式,只对它增加了若干的特殊要求。插件工厂要求指明某一环境下,接口与哪一个实现连接的指令在一个单独的、代码之个的地方声明,以便配置具有可管理性,此外,与实现的连接必须是在运行时动态进行,而不是在编译时进行,这样才能在重配置后无需重新编译。
文本文件可以很好的描述连接规则。插件工厂不过简单的读取文本文件,查找指定当前环境下所需的接口对应哪一个实现的项,然后返回相应的实现。
插件模式在具有反射机制的语言中可以充分发挥其优势,因为工厂可以动态构造实现对象,而无需在编译时就与实现类存在依赖关系。当使用反射机制时,配置文件必须包含接口名到实现类的映射。工厂可以置于框架包中,而且当在配置选项中增加新的实现类时无需改变工厂。
即使没有使用反射机制的程序语言,插件仍然有其存在的价值,它创建了一个中心配置点,仍然可以使用一个文本文件来设置连接规则,唯一区别在于你的工厂将使用一个条件判断逻辑来将接口映射到实现。为了执行层间和包间依赖关系的编译检查,可以将工厂放到一个独立的包中以避免破坏编译过程。
使用场景
只要有行为在不同运行环境要求不同的实现时,就应使用插件模式。