delphi中的接口和构造函数

时间:2011-11-03 03:50:06

标签: delphi interface constructor

我正在为业务对象编写一个框架。由于以下原因,我大量使用接口:

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

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

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

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

谢谢!

===编辑===

我的问题中的一点是构造函数的参数..在框架中很多对象需要一些其他的工作..答案很好地解决了关注点,但我仍然看不出如何解决参数问题..

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

4 个答案:

答案 0 :(得分:8)

Factory方法允许您在一个地方注册接口的实现者,并允许其余代码“只需要一个实现者。”

Factory.GetImplementorOf(IMyInterface)

然后返回一个接口引用。

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

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

多个实例可以派上用场,例如在处理可能无法使用的重复(d)服务时,您可以选择一个恰好正常的服务。

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


  

工厂准备在某些工作中使用构造函数参数   干净的方式??

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

如果你想在每个类的基础上有更多特定的构造函数,你必须

  • 创建更多的工厂,这使得只有一个点来注册接口的实现者
  • 允许在每个接口/类的基础上构建初始化方法,这些方法应该在构造之后立即调用,这样就可以打开代码,使其更加不可变。
  • 或想出一种将构造函数签名知识合并到工厂中的方法。

在某个阶段,我选择了第三个选项。通过创建

工厂
  • 需要注册具有抽象基类的接口
  • 要求实现者从抽象基类下载
  • 将实现者作为元类引用而不是实例
  • 返回
    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;

缺点:

  • 必须声明接口和抽象基类是非常麻烦的。
  • 它破坏了单一继承语言中接口的“多重继承”优势。
  • 您需要在整个代码中传播接口/抽象基类对的知识,否则您仍然无法使用特定于类的构造函数。泛型可能在这里有所帮助,但我还没有研究过。
  • 如果您没有相同(一组)接口的多个实现者,那么它没有用处。
  • 即使您只想进行单元测试的多个实现器,它似乎也有些过分。我发现在测试单元中声明的虚拟类与类接口的相关部分更有帮助和有效。

总而言之,我已经回到标准构造函数/特定的Initialization对方法。编写代码扫描单元测试以检查来自工厂的每个GetImplementor调用是否跟随初始化调用应该相当容易。尽管理论上的类不再像使用特定构造函数那样不可变,但它仍然适用于所有实际目的。如果你想确保只在构造之后立即调用Initialize方法,那么应该很容易添加。

答案 1 :(得分:3)

接口不会消除实现对象的需要。您使用的每个接口都必须具有实现对象。所以你的代码需要调用构造函数。

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

不使用方法来抽象界面创建,你的目标没有。 2将不完整。

答案 2 :(得分:3)

如果您觉得需要在接口上添加构造函数,那么您做错了。

接口只是功能声明。如何提供该功能与接口无关。实际上,如何创建实现对象应该完全不关心接口的使用者。这就是依赖注入的用武之地。

依赖注入是指接口的实现与实际使用接口的代码完全分离的概念。它不仅仅是一个工厂类(由Marjan巧妙地描述),因为它允许您从接口中完全解耦实现类的声明和实现。

因此,当您声明一个接口时,依赖注入容器可以自动创建/获取已实现对象的实例,从而无需您创建它。通过这种方式,您的应用程序变得只是接口连接在一起,而不用担心构造任何东西。您的库代码仅通过DI容器显示。

Delphi Spring Framework提供了一个非常好用的DI容器供您使用。你可以在这里找到Delphi Spring Framework和Spring Container:

http://code.google.com/p/delphi-spring-framework/

答案 3 :(得分:1)

Nick Hodges presentation at CodeRage简单地说,你应该将建筑工作转移到一个由其自己负责创建对象的类。这通常被称为“工厂”模式。

从逻辑的角度来看,这对我来说是有意义的,因为它是SOLID原则中'S'的特定实例;单一责任。对象的创建应该是一个单一的责任(工厂),将对象链接在一起以解决问题(一个真实对象的组合加上五个模拟的,将是单元测试,或五个真实对象的组合来解决一个问题生产代码库中的问题。)