Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
delphi中的接口和构造函数_Delphi_Interface_Constructor - Fatal编程技术网

delphi中的接口和构造函数

delphi中的接口和构造函数,delphi,interface,constructor,Delphi,Interface,Constructor,我正在为业务对象编写一个框架。。我大量使用接口是因为: 1) 自动内存管理 2) 关注点分离 通常构造函数有一些参数是框架的对象,但我不能将它们放在接口中 我的问题是,如果我使用接口来分离实现它们的类,为什么我的代码仍然绑定到实现接口的具体类来调用构造函数及其参数。。及 将创建者代码放入工厂方法的优点是什么?(我还没用的东西…) 谢谢 ==编辑=== 我问题的重点是构造器的参数。。在框架中,许多对象需要一些其他对象才能工作。。答案很好地解决了关注点分离的问题,但我仍然不知道如何解决参数问题 如果

我正在为业务对象编写一个框架。。我大量使用接口是因为:

1) 自动内存管理
2) 关注点分离

通常构造函数有一些参数是框架的对象,但我不能将它们放在接口中

我的问题是,如果我使用接口来分离实现它们的类,为什么我的代码仍然绑定到实现接口的具体类来调用构造函数及其参数。。及

将创建者代码放入工厂方法的优点是什么?(我还没用的东西…)

谢谢

==编辑===

我问题的重点是构造器的参数。。在框架中,许多对象需要一些其他对象才能工作。。答案很好地解决了关注点分离的问题,但我仍然不知道如何解决参数问题


如果我不采用构造函数方式,我应该采用“过程初始化”方式(在接口中)和“CheckObjectInitialized”(受保护)方式(在对象的每个方法中)。。这将如何变得更干净?

接口不需要实现对象。您使用的每个接口都必须有一个实现对象。因此,您的代码需要调用构造函数

工厂模式和其他创建模式允许您使对象创建更加灵活和模块化。这些创建模式允许您隐藏所有实现类声明,例如,将它们放在单元的实现部分


如果不使用方法来抽象接口创建,您的目标2将是不完整的。

工厂方法将允许您在一个地方注册接口的实现者,并允许您的其余代码“只要求一个实现者”

然后返回一个接口引用

这取决于你想如何实施工厂。您可以为每个请求的接口创建新实例,维护已创建实例的池并返回对这些实例的引用,或者根据请求的接口进行混合

您还可以决定是否希望工厂允许同一接口的多个实现者(那么如何选择正确的实现者),或者为每个接口强制一个实现者,或者混合使用

例如,在处理可能有时不可用的重复(d)服务时,多个实例可以派上用场,这样您就可以选择一个恰好可用的实例

提供一个GetImplementorOf(接口数组)也是一个想法。因此,您可以有多个IDump实现者,但可以通过它们转储信息的方式来区分它们:例如,一个实现者认为IDump是IHTML格式的对象


工厂是否准备在某些情况下使用施工人员参数 清洁方式

现在,这是一个有趣的问题。不,他们本身并不是。工厂通常使用标准构造函数,可能使用“所有者”和/或“Id”参数

如果您希望在每个类的基础上使用更具体的构造函数,那么必须

  • 创建更多的工厂,这样就不能用一个点来注册接口的实现者
  • 允许在每个接口/类的基础上初始化方法,这些方法应该在构造之后立即调用,这会使代码变得容易遗忘,并减少类的不可变性
  • 或者想出一种方法将构造器签名知识融入工厂
在某个阶段,我选择了第三种选择。通过创建一个

  • 需要向抽象基类注册接口
  • 从抽象基类派生所需的实现者
  • 作为元类引用而不是实例返回实现者
TFactory=class(…) 公众的 过程注册表接口(const aGUID:TGUID;const aAbstractBase:TClass); 过程寄存器implementor(const aGUID:TGUID;const aImplementor:TClass); 函数GetImplementor(const aGUID:TGUID):TClass; 缺点:

  • 必须同时声明接口和抽象基类是一件非常麻烦的事情
  • 它克服了单一继承语言中接口的“接口多重继承”优势
  • 您需要在整个代码中传播接口/抽象基类对的知识,否则仍然无法使用特定于类的构造函数。泛型可能会有帮助,但我还没有研究过
  • 如果没有相同(一组)接口的多个实现者,那么它就没有真正的用途
  • 即使只是为了单元测试而需要多个实现者,这似乎有些过分。我发现在测试单元中声明的虚拟类以及类接口的相关部分更有用、更有效
总而言之,我回到了标准构造函数/特定初始化对方法。编写一个代码扫描单元测试来检查工厂的每个GetImplementor调用之后是否都有一个初始化调用,应该相当容易。尽管在理论上,类不再像使用特定构造函数时那样是不变的,但在实际应用中它仍然是不变的。如果您想确保只在构造之后调用Initialize方法,那么这应该很容易添加。

简单地说,您应该将构造作业移动到一个类,该类的唯一职责是创建对象。这通常被称为“工厂”模式

从逻辑的角度来看,这对我来说是有意义的,因为它是固体原则中“S”的一个具体例子;单一责任。创建对象应该是一项单独的责任(工厂),将对象链接在一起以解决问题(一个re的组成)也是一项责任
Factory.GetImplementorOf(IMyInterface)
TFactory = class(...) public procedure RegisterInterface(const aGUID: TGUID; const aAbstractBase: TClass); procedure RegisterImplementor(const aGUID: TGUID; const aImplementor: TClass); function GetImplementor(const aGUID: TGUID): TClass;