Сделал тут одну из реализаций 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.
Комментариев нет:
Отправить комментарий