我建议您执行以下步骤。
首先,使用支持多个部分/范围概念的配置文件语法,最好是可嵌套范围。例如,在我所说的意义上,XML 元素是一个可嵌套的范围,而“.ini”文件提供了不可嵌套的部分。 Java 属性文件不提供对作用域的直接支持,但您可以通过使用语法x.y.z 来模拟这种支持,在作用域z 中表示变量y,而后者又嵌套在作用域x 中。 Config4*(我开发的)提供对嵌套作用域的直接支持。
其次,编写一个可配置的Foo类的构造函数,如下伪代码所示:
Foo(Configuration cfg, String scope) {
_x = cfg.lookup(scope + ".x");
_y = cfg.lookup(scope + ".y");
_z = cfg.lookup(scope + ".z");
_bar = new Bar(cfg, scope + ".bar");
}
在上面的伪代码中,我使用_ 前缀来表示一个实例变量,并且我假设Configuration 类有一个lookup() 操作,它采用一个作用域名称,例如,cfg.lookup("foo.bar.abc") 将返回foo.bar 范围内的 abc 变量的值。
第三,你的应用程序的main()函数可以写成如下伪代码:
main(...) {
String configFileName = ...; // obtain from command-line argument
String scope = ...; // obtain from command-line argument
Configuration cfg = parseConfigurationFile(configFileName);
Foo foo = new Foo(cfg, scope + ".foo");
... // create other configured objects
doRealWork(foo, ...);
}
最后,应用程序的命令行参数应指定:(1) 配置文件的名称,以及 (2) 包含用于运行应用程序的配置变量的顶级范围(在配置文件中)。例如,假设example.cfg 的结构如下:
instance1 {
foo {
x = "a value";
y = "another value";
z = "yet another value";
bar {
...
}
}
... # configuration for other objects
}
instance2 {
foo {
x = "...";
y = "...";
z = "...";
bar {
...
}
}
... # configuration for other objects
}
您可以使用myApp.exe -cfg example.cfg -scope instance1 运行您的应用程序。
上述建议有以下好处:
- 您的应用程序可以创建多个
Foo 对象,每个对象都可以进行不同的配置,只需将不同的scope 参数传递给每个对象的构造函数即可。
- 如果需要,用户可以灵活地将多组配置变量存储在单个配置文件中。例如,用户可能有不同的配置变量集用于: (1) 不同的单元测试; (2) 开发、UAT和生产环境; (3) 复制服务器应用程序的多个实例。
- 随着时间的推移,您可以编写一个遵循上述设计原则的可配置类库。该可配置类库可以在多个应用程序中重复使用。
我已经在我编写的几个基于 C++ 和 Java Config4* 的应用程序中使用了上述方法,并且对我来说效果很好。如果您使用的语言内置了对反射的支持(例如 Java),那么另一种方法是使用依赖注入框架。如果您不知道那是什么,请在 Internet 上搜索“依赖注入”、“控制反转”或“Spring 框架”。