传统方式:
function ReadConfig:string;
begin
with TIniFile.Create(someFile) do
begin
try
result :=ReadString(aSection,aConfigName);
finally
Free;
end;
end;
end;
当需要更改为从xml读取文件后,需要修改这个函数,或者重载这个函数,不可避免的所在单元的代码将不断扩大,
而使用面向接口方式将会这样来撰写
定义接口
IConfig = interface
function GetConfig:string;
end;
ini实现
TIniConfig = class(TInterfacedObject ,IConfig)
function GetConfig:string;
end;
end;
调用者的代码将不再是:
ReadConfig;
而是
(TIniConfig.Create as IConifg).GetConfig;
当实现了
TXmlConfig = class(TInterfacedObject ,IConfig)
function GetConfig:string;
end;
end;
那么调用者可以
(TXmlConfig.Create as IConifg).GetConfig;
这表示调用者可以使用不同的类来为自己提供服务,例如可以声明一个ITransaction,定义事务的3个方法,
那么,你可以有两个实现-----基于bde的实现和基于ado的实现,当你切换数据连接时将非常的方便.
插件
然后这样的系统在架构上已经达到了我们的要求,唯一不太完美的是一旦有了切换,我们需要重新编译整个程序,分发.怎么解决它,我们需要一个可以动态载入到程序中的实现,并能配置容器告知容器我们切换了实现..
对的,在java下我们可以发布jar包,而jar包的类通过xxx.xxx.xxx方式保证了类的唯一性,java中各种框架的配置文件90%都有class="xxx.xxx.xxx"之类的声明,而Spring框架更是将这种插件的方式用到了一个可以说是理想的境界,这种机制叫做"依赖注入",而我们在delphi中该如何实现类似的应用(水平不够,不敢说相同的应用)
构思一下:
容器(即应用程序)完全按照面向接口编程
容器读入一个外部配置文件来确定每个接口的具体实现类的名称
载入bpl(bpl中注册了实现某接口的类,以让宿主程序可以访问到)
通过rtti(类似java的反射)创建类的实例
将该实例as 成接口,容器使用该实例完成工作.
当提供某个接口的不同实现时,发布bpl,更新容器配置文件,完成切换
这就是我想开发的插件系统,一个最花精力的事情就是容器到底需要哪些接口来完成一个应用.那么我们需要对现有的应用进行合理的分割,将可能出现变化的部分抽象成接口,将原有的代码实现在一个实现该接口的类中,设想一下一个完整的C/S结构的mis系统需要哪些接口来完成整个应用.
主程序
一个完全由接口驱动的程序,它调用各种接口完成软件的功能.(当然并不是绝对的,如果你的某个功能并不需要外部来提供的化)
插件s(注意,加了s复数形式)
放在同一目录下,一个完整的插件应该有两个同名文件,一个是含有实现某