如何在 Delphi 中配置Spring4D中的依赖项?

628mspwn  于 2022-11-23  发布在  Spring
关注(0)|答案(1)|浏览(181)

我正在阅读Nick Hodges的书“ Delphi 中的依赖注入”。“注册工厂”一章考虑了这个例子:还有一个接口:

ICoffeeMaker = interface
['{73436E03-EF65-44F5-9606-F706156CBEB5}']
  procedure MakeCoffee;
end;

...以及实现它的类:

type
  TCoffeeMaker = class(TInterfacedObject, ICoffeeMaker)
    private
      FCoffeeBrand: string;
      FBrewingMinutes: integer;
    public
      constructor Create(const aCoffeeBrand: string; const aBrewingMinutes: integer);
      procedure MakeCoffee;
    end;

constructor TCoffeeMaker.Create(const aCoffeeBrand: string; const aBrewingMinutes: integer);
begin
  inherited Create;
  FCoffeeBrand := aCoffeeBrand;
  FBrewingMinutes := aBrewingMinutes;
end;

procedure TCoffeeMaker.MakeCoffee;
begin
  WriteLn('Pour hot water over the ', FCoffeeBrand, ' so that it brews for ', FBrewingMinutes, ' minutes.');
end;

接下来,声明一个工厂函数以创建ICoffeeMaker的示例:

{$M+}
  TCoffeeMakerFactory = reference to function(const aCoffeeBrand: string; const aBrewingMinutes: integer): ICoffeeMaker;
  {$M-}

......整个过程都记录在容器中:

procedure RegisterStuff(aContainer: TContainer);
begin
  aContainer.RegisterType<ICoffeeMaker, TCoffeeMaker>.AsDefault;
  aContainer.RegisterFactory<TCoffeeMakerFactory>;
  aContainer.Build;
end;

然后给出了主程序的代码:

var
  CoffeeName: string;
  BrewingMinutes: integer;
  CoffeeMakerFactory: TCoffeeMakerFactory;
  CoffeeMaker: ICoffeeMaker;
begin
  Write('What kind of coffee do you want to make? ');
  ReadLn(CoffeeName);

  Write('How many minutes? ');
  ReadLn(BrewingMinutes);

  CoffeeMakerFactory := Container.Resolve<TCoffeeMakerFactory>();
  CoffeeMaker := CoffeeMakerFactory(CoffeeName, BrewingMinutes);
  CoffeeMaker.MakeCoffee;
end;

作者写道,没有必要在容器中注册TCoffeeMaker。但是突然我们会有一些TKitchen类,该类将ICoffeeMaker作为依赖项。问题是:如果真的有一个TKitchen类实现了IKitchen接口,该接口在构造函数中将ICOfeeMaker作为参数,那该怎么办呢?我将在容器中注册它:

begin
  //...
  aContainer.RegisterType<IKitchen, TKitchen>;
  //...
end;

...然后在主程序中创建:

begin
  //...
  Kitchen := Container.Resolve<IKitchen>();
  //...
end;

在这种情况下,如何选择所需的实现并配置创建的ICoffeeMaker示例?

dsf9zpds

dsf9zpds1#

老实说,这个代码示例有点糟糕。
你不需要为不同的品牌或冲泡时间创建新的咖啡机。这些是不同的事情。品牌和冲泡时间应该是MakeCoffee方法的参数。如果咖啡机有一些内部部件,比如研磨咖啡豆的研磨机或类似的东西,那么它可以是一个ctor参数。
如果你像这样修改代码,你的问题就消失了,因为你不需要创建新的咖啡机,只是为了用不同的冲泡时间冲泡不同品牌的咖啡。
当然,你可以有一个不同的模型,这些东西确实传递到ctor,但然后你有一个咖啡机与固定的品牌和酿造时间,你简单的“按下按钮”得到一杯咖啡,它为你做。
现在,如果你有一个厨房,有一个咖啡机,你不会创建一个新的厨房,一个新的咖啡机只是为了得到一个不同的品牌或酿造时间,你呢?是的,我比较真实的世界与软件在这里,但它表明,有些东西是不正确的与这个软件模型。

相关问题