Сделал тут одну из реализаций 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. Вот один из примеров кода:
Вот это всё полностью сгенерировано с модели.
Нет НИ ОДНОЙ строчки РУКОПИСНОГО кода.
Грубо говоря так:
Рисуем:
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.
Комментариев нет:
Отправить комментарий