четверг, 24 июля 2014 г.

Сделал тут одну из реализаций Dependency Injection на UML и "кодогенерации"

Сделал тут одну из реализаций Dependency Injection на UML и "кодогенерации".

Грубо говоря так:

Рисуем:

Class A
Class B
Interface C
Class A uses -> Interface C
Class B implements -> Interface С

И связь:

Class B As Interface C injects to -> Class A

Получаем:

new Class CFactory produces -> Interface C
Class A uses -> Class CFactory
Class B uses -> Class CFactory
Class B register in -> Class CFactory
Class A gets Interface C from -> Class CFactory

Таким образом получаем "синтетический" класс CFactory, про который ЗНАЕТ класс A и в котором РЕГИСТРИРУЕТСЯ класс B.

При этом класс A умеет получать экземпляры класса B (видимые как интерфейс C) через ФАБРИКУ CFactory.

При этом - класс A НАПРЯМУЮ не знает про класс B, а знает только про фабрику CFactory.

А класс B умеет инстанцироваться как интерфейс C через фабрику CFactory. При этом он НАПРЯМУЮ (с точки зрения uses модулей) НЕ ЗНАЕТ про класс A.

Фабрика CFactory (и дополнительная обвязка) полностью генерируется с модели.

Генерируемый код кому-то интересен?

При этом если нарисовать так:

Class A
Class B
Interface C
Class A uses -> Interface C
Class B implements -> Interface С
Class D uses -> Interface С

Class B As Interface C injects to -> Class A
Class B As Interface C injects to -> Class D

то получаем:

new Class CFactory produces -> Interface C
Class A uses -> Class CFactory
Class B uses -> Class CFactory
Class B register in -> Class CFactory
Class A gets Interface C from -> Class CFactory
Class D uses -> Class CFactory
Class D gets Interface C from -> Class CFactory

Ну и далее "по индукции".

UML диаграмма "исходного" и "конечного кода" нужна?

Update. Вот один из примеров кода:

Вот это всё полностью сгенерировано с модели.

 Нет НИ ОДНОЙ строчки РУКОПИСНОГО кода.

unit evTextPara_InterfaceFactory;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Generated from UML model, root element: interfacefactory::class Shared Delphi::Everest::InterfaceFactories::TevTextPara
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ! Полностью генерируется с модели. Править руками - нельзя. !

{$Include ..\Everest\evDefine.inc}

interface

uses
  evLeafPara_InterfaceFactory,
  l3IID,
  k2ToolPrim,
  l3Variant
  ;

type
 TevTextParaInterfaceFactory = class(TevLeafParaInterfaceFactory)
 protected
 // overridden protected methods
   function COMQueryTool(aTag: Tl3Tag;
     const aIID: Tl3GUID;
     out theTool;
     const aProcessor: Ik2Processor): Boolean; override;
 public
 // overridden public methods
   function QueryTool(aTag: Tl3Variant;
     const ID: Tl3IID;
     out I: Tk2ToolPrim): Boolean; override;
 end;//TevTextParaInterfaceFactory

implementation

uses
  nevRealTools,
  nevTools,
  nevGUIInterfaces,
  l3Interfaces
  {$If defined(evUseVisibleCursors)}
  ,
  evTextParaCursor
  {$IfEnd} //evUseVisibleCursors

  {$If defined(evNeedPainters)}
  ,
  evTextParaPainterEx
  {$IfEnd} //evNeedPainters
  ,
  nevTextPara
  {$If defined(evUseVisibleCursors)}
  ,
  evTextCursorPair
  {$IfEnd} //evUseVisibleCursors

  {$If defined(evNeedHotSpot)}
  ,
  evTextParaHotSpotTester
  {$IfEnd} //evNeedHotSpot

  {$If defined(evUseDeadCursor) AND defined(evUseVisibleCursors)}
  ,
  evDeadCursor
  {$IfEnd} //evUseDeadCursor AND evUseVisibleCursors
  ,
  evTextParaStringImpl,
  nevTextParaAnchor,
  nevTextParaInevTextParaMapper
  ;

// start class TevTextParaInterfaceFactory

function TevTextParaInterfaceFactory.QueryTool(aTag: Tl3Variant;
  const ID: Tl3IID;
  out I: Tk2ToolPrim): Boolean;
 {-}
begin
 Result := true;
 {$If defined(evUseVisibleCursors)}
 if ID.EQ(ev_iidCursor) then
  I := TevTextParaCursor.Create(aTag)
 else
 {$IfEnd} //evUseVisibleCursors
 {$If defined(evUseVisibleCursors)}
 if ID.EQ(ev_iidBlock) then
  I := TevTextCursorPair.Create(aTag)
 else
 {$IfEnd} //evUseVisibleCursors
  Result := inherited QueryTool(aTag, ID, I);
end;//TevTextParaInterfaceFactory.QueryTool

function TevTextParaInterfaceFactory.COMQueryTool(aTag: Tl3Tag;
  const aIID: Tl3GUID;
  out theTool;
  const aProcessor: Ik2Processor): Boolean;
 {-}
begin
 Result := true;
 {$If defined(evNeedPainters)}
 if aIID.EQ(IevPainter) then
  IevPainter(theTool) := TevTextParaPainterEx.Make(aTag)
 else
 {$IfEnd} //evNeedPainters
 if aIID.EQ(InevTextPara) then
  InevTextPara(theTool) := TnevTextPara.Make(aTag)
 else
 {$If defined(evNeedHotSpot)}
 if aIID.EQ(InevHotSpotTester2) then
  InevHotSpotTester2(theTool) := TevTextParaHotSpotTester.Make(aTag)
 else
 {$IfEnd} //evNeedHotSpot
 {$If defined(evUseDeadCursor) AND defined(evUseVisibleCursors)}
 if aIID.EQ(IevSavedCursor) then
  IevSavedCursor(theTool) := TevTextParaDeadCursor.Make(aTag)
 else
 {$IfEnd} //evUseDeadCursor AND evUseVisibleCursors
 if aIID.EQ(Il3WordsSeq) then
  Il3WordsSeq(theTool) := TevTextParaStringImpl.Make(aTag)
 else
 if aIID.EQ(InevAnchor) then
  InevAnchor(theTool) := TnevTextParaAnchor.Make(aTag)
 else
 if aIID.EQ(InevPara) then
  Result := TnevTextParaInevTextParaMapper.Make(aTag, aIID, theTool, aProcessor)
 else
 if aIID.EQ(InevParaInternal) then
  Result := TnevTextParaInevTextParaMapper.Make(aTag, aIID, theTool, aProcessor)
 else
 if aIID.EQ(InevLeafPara) then
  Result := TnevTextParaInevTextParaMapper.Make(aTag, aIID, theTool, aProcessor)
 else
  Result := inherited COMQueryTool(aTag, aIID, theTool, aProcessor);
end;//TevTextParaInterfaceFactory.COMQueryTool

end.

Комментариев нет:

Отправить комментарий