首先,对不起,如果标题有点令人困惑。
我打算开发一个小型的erp应用程序。这个应用程序将使用插件/插件。这个插件可能会添加或扩展基本应用程序的某些模块。
例如,我有TCustomer类,其属性为“id”,“name”。 插件1将添加属性“dateofbirth”。 插件2将添加属性“balance”和方法“GetBalance”。
插件1和插件2彼此不了解。可能安装了插件1而不是插件2,反之亦然。所以这两个插件都必须继承基本的tcustomer类。
问题是安装了两个插件时。如何在两个插件中获得扩展属性?我还必须扩展表单以添加控件以显示新属性。
可以用delphi完成吗?实现这一目标的最佳方法是什么?也许你可以指点我的一些例子?
谢谢,抱歉我的英语不好 Reynaldi答案 0 :(得分:5)
好吧,正如您已经知道的那样,您不能拥有多个插件来继承扩展现有类。它会混淆任何应用程序,包括任何程序员处理代码。
您需要的是TCustomer类中的某种类型的注册机制,其中每个插件都可以注册其特定属性,或者在创建(初始化),加载,存储或删除TCustomer实例时提供一些回调函数。毕竟,核心TCustomer确实不需要了解插件的更多信息,而不是它们可能存在的事实。
根据您打算如何加载/存储数据,核心TCustomer类甚至不必了解扩展。只要TCustomer / TOrder / TWOUT被初始化/加载/保存/删除,就可以让持久性机制了解插件,并为它们提供一种注册回调函数的方法。
您还必须让GUI了解插件,并为他们提供注册UI的方法,让主GUI为每个插件的特定控件创建额外的选项卡或其他选项。
抱歉没有代码示例。我自己还没有实现这个,虽然我考虑过这个设计并且它已经列入了我要玩的东西。
那就是说,为了给你一个想法,基本机制可能看起来像这样:
TBaseObject = class; // forward declaration
// Class that each plug-in's extensions of core classes needs to inherit from.
TExtension = class(TObject)
public
procedure Initialize(aInstance: TBaseObject);
procedure Load(aInstance: TBaseObject);
procedure Store(aInstance: TBaseObject);
procedure Delete(aInstance: TBaseObject);
end;
// Base class for all domain classes
TBaseObject = class(TObject)
private
MyExtensions: TList<TExtension>;
public
procedure RegisterExtension(const aExtension: TExtension);
procedure Store;
end;
procedure TBaseObject.RegisterExtension(const aExtension: TExtension);
begin
MyExtensions.Add(aExtension);
end;
procedure TBaseObject.Store;
var
Extension: TExtension;
begin
// Normal store code for the core properties of a class.
InternalStore;
// Give each extension the opportunity to store their specific properties.
for Extension in MyExtensions do
Extension.Store(Self);
end;
答案 1 :(得分:1)
这种“不断发展”的阶级是某种多重继承。
我认为你最好使用接口而不是类。
也就是说,每个插件都将提供类实现,但您将使用接口和接口工厂。
请参阅this article about "why we need interfaces"或this article from our blog about interfaces and a comparison with classes。
您可以测试一个类是否实现了一个接口:对于像您这样的插件系统,这可能是实现开放实现的最佳方式。 Duck typing非常适合插件。整个Delphi IDE(和Windows本身)正在为其插件系统使用接口(通过COM for Windows)。对于不太强大的实现模式,您可以使用非接口,但可以使用后期绑定:请参阅此SO问题的答案。
查看the SOLID principles,尤其是单一责任原则。您的问题直接违反了这一原则:您尝试混合客户个人信息(如姓名)和会计(如余额)。如果你的项目成长,你可能会被这样的设计所困扰。