gpt4 book ai didi

delphi - 构造函数依赖注入(inject)替代方案

转载 作者:行者123 更新时间:2023-12-03 18:30:01 26 4
gpt4 key购买 nike

我正在独自从事一个员工计时项目,该项目使用数据库来存储时间表条目。我在该项目中使用 Delphi Pro 10.2.3 Tokyo,并创建了一个包装类库,以方便使用普通类等数据集。例如,要访问 Employee 表中的 FirstName 字段,我可以写 LFirstName := FEmployee.FirstName;而不是 LFirstName := Dataset.FieldByName('FirstName').AsString;

我的一些类有大量依赖项(多达八个),我通过类的构造函数注入(inject)这些依赖项。我使用域对象来创建所需的接口(interface)并将它们注入(inject)到正在创建的类中。
一些被注入(inject)的接口(interface)本身也非常复杂,并且开始难以跟踪域对象中的所有内容。

注入(inject)的依赖项包括为计算字段提供查找值的其他表的包装器接口(interface)、指向创建类使用的创建对象的函数的指针或解析主/从关系的回调函数。这些关系是静态的,需要在构造函数中设置,以便在创建类时任何计算字段都将起作用。

是否有任何替代构造函数注入(inject)的方法可能会降低构造函数的复杂性,同时保持解耦类。这是我的一个模块中用于时间表条目的代码示例。

unit LevelPay.DbModel.TimesheetEntry;

interface

uses
Data.Db
, FireDAC.Comp.DataSet
, MyLib.Model.Interfaces
, LevelPay.Model.Types
, LevelPay.Model.Constants
, LevelPay.Model.Interfaces
, LevelPay.DbModel.AppModel
;

type
TDbCustomTimesheetEntry = class(
TDbAppModel<ITimesheetEntry>,
ITimesheetEntry
)
strict private
FCopyFunc: TCopyFunc<ITimesheetEntry>;
procedure ClearFilter;
procedure FilterEntries(const ADate: TDate);
strict protected
FTimesheet: ITimesheet;
FID: TField;
FEmployeeID: TField;
FPayPeriodEndDate: TField;
FFiscalYearEndDate: TField;
FFiscalYearStartDate: TField;
FRowNbr: TField;
FEntryTypeID: TField;
FDateIn: TField;
FTimein: TField;
FDateOut: TField;
FTimeOut: TField;
FCreatedBy: TField;
FCreatedTimestamp: TField;
FLastModifiedBy: TField;
FLastModifiedTimestamp: TField;
FNote: TField;
FClockable: TField;
FClockableHours: TField;
FDayOfWeek: TField;
FDifference: TField;
FEmployeeName: TField;
FEntryTypeCaption: TField;
FTimeElapsed: TField;
FDateIndex: TFDIndex;
FTimeScheduled: TField;
FScheduledTimeIn: TField;
FScheduledTimeOut: TField;
FWeekOf: TField;
function GetID: TIdentifier;
function GetModel: ITimesheetEntry; override;
function GetClockable: Boolean;
function GetClockableHours: THours;
function GetDateIn: TDate;
function GetDateOut: TDate;
function GetDifference: THours;
function GetEmployeeID: TIdentifier;
function GetEmployeeName: string;
function GetPayPeriodEndDate: TDate;
function GetFiscalYearStartDate: TDate;
function GetFiscalYearEndDate: TDate;
function GetEntryTypeID: TIdentifier;
function GetEntryTypeCaption: TCaption;
function GetPlaceholder: Boolean;
function GetRowNbr: TRowNbr;
function GetScheduledTimeIn: TTime;
function GetScheduledTimeOut: TTime;
function GetTimeElapsed: THours;
function GetTimein: TTime;
function GetTimeOut: TTime;
function GetTimeScheduled: THours;
function GetWeekOf: TDate;
function GetWeekDay: string;
function GetCreatedBy: TUserName;
function GetCreatedTimestamp: TDateTime;
function GetLastModifiedBy: TUserName;
function GetLastModifiedTimestamp: TDateTime;
function GetNote: AnsiString;
function GetEntry: ITimesheetEntry;
function GetTimesheet: ITimesheet;
function GetHasEntries: Boolean;
function Find(AModel: ITimesheetEntry): Boolean; override;
procedure DoUpdate(AModel: ITimesheetEntry); override;
procedure Load; virtual;
procedure CreateFields; override;
procedure CreateCalcFields; override;
procedure CreateIndexes; override;
procedure FormatFields; override;
procedure OnCalcFields(Dataset: TDataset); override;
procedure OnNewRecord(Dataset: TDataset); override;
public
constructor Create(
ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>;
ACopyFunc: TCopyFunc<ITimesheetEntry>;
ATimesheet: ITimesheet;
ACreateFields: Boolean
); reintroduce;
property ID: TIdentifier read GetID;
property EmployeeID: TIdentifier read GetEmployeeID;
property PayPeriodEndDate: TDate read GetPayPeriodEndDate;
property FiscalYearEndDate: TDate read GetFiscalYearEndDate;
property FiscalYearStartDate: TDate read GetFiscalYearStartDate;
property EntryTypeID: TIdentifier read GetEntryTypeID;
property EntryTypeCaption: TCaption read GetEntryTypeCaption;
property RowNbr: TRowNbr read GetRowNbr;
property Clockable: Boolean read GetClockable;
property ClockableHours: THours read GetClockableHours;
property DateIn: TDate read GetDateIn;
property EmployeeName: string read GetEmployeeName;
property ScheduledTimeIn: TTime read GetScheduledTimeIn;
property ScheduledTimeOut: TTime read GetScheduledTimeOut;
property TimeIn: TTime read GetTimein;
property DateOut: TDate read GetDateOut;
property TimeOut: TTime read GetTimeOut;
property TimeElapsed: THours read GetTimeElapsed;
property Placeholder: Boolean read GetPlaceholder;
property TimeScheduled: THours read GetTimeScheduled;
property Difference: THours read GetDifference;
property WeekDay: string read GetWeekDay;
property WeekOf: TDate read GetWeekOf;
property CreatedBy: TUserName read GetCreatedBy;
property CreatedTimestamp: TDateTime read GetCreatedTimestamp;
property LastModifiedBy: TUserName read GetLastModifiedBy;
property LastModifiedTimestamp: TDateTime read GetLastModifiedTimestamp;
property Note: AnsiString read GetNote;
property Timesheet: ITimesheet read GetTimesheet;
end;

TDbSourceEntry = class(TDbCustomTimesheetEntry, ISourceEntryList)
strict private
FLoadTimesheetEntries: TLoadTimesheetProc;
FElectionList: ILevelPayElectionList;
FPositionList: IHourlyPositionList;
strict protected
procedure BeforePost(Dataset: TDataset); override;
procedure Load; override;
public
constructor Create(
ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>;
ATimesheet: ITimesheet;
ACopyFunc: TCopyFunc<ITimesheetEntry>;
AProc: TLoadTimesheetProc;
AElectionList: ILevelPayElectionList;
APositionList: IHourlyPositionList;
ACreateFields: Boolean = True
); reintroduce;
end;

TDbDummyEntry = class(TDbCustomTimesheetEntry, IDummyEntryList)
strict private
FPlaceholderID: TIdentifier;
FClosureList: ISchoolClosureList;
procedure EntryTypeIDOnChange(Sender: TField);
strict protected
procedure AddPlacedholder(ADate: TDate; ARowNbr: TRowNbr);
procedure CreateFields; override;
procedure DoAdd(AModel: ITimesheetEntry); override;
property PlaceholderID: TIdentifier read FPlaceholderID write FPlaceholderID;
public
constructor Create(
ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>;
ACopyFunc: TCopyFunc<ITimesheetEntry>;
ATimesheet: ITimesheet;
AClosureList: ISchoolClosureList;
ACreateFields: Boolean
); reintroduce;
end;

TDbTimesheetEntry = class(TDbDummyEntry, ITimesheetEntryList)
strict private
FClone: TFDDataset;
FSource: ISourceEntryList;
function GetNextRowNbr: TRowNbr;
strict protected
function WorkweekList: IWorkweekList;
procedure Clear;
procedure Load; override;
public
procedure Add(AModel: ITimesheetEntry); //replaces inherited add
procedure Delete(AModel: ITimesheetEntry); //replace inherited delete
procedure Update(OldModel, NewModel: ITimesheetEntry);
constructor Create(
ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>;
ACopyFunc: TCopyFunc<ITimesheetEntry>;
ATimesheet: ITimesheet;
ASourceFunc: TSourceListFunc;
AClosureList: ISchoolClosureList;
ACreateFields: Boolean
); reintroduce;
end;

implementation

uses
System.SysUtils
, System.Classes
, System.Variants
, System.DateUtils
, FireDAC.Comp.Client
, DateTimeHelper
, LevelPay.Model.Helpers
;

{ TCustomShift }

procedure TDbCustomTimesheetEntry.ClearFilter;
begin
CancelRange;
end;

constructor TDbCustomTimesheetEntry.Create(ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>; ACopyFunc: TCopyFunc<ITimesheetEntry>;
ATimesheet: ITimesheet; ACreateFields: Boolean);
begin
inherited Create(ADataset, AModelFunc, ACreateFields);
FCopyFunc := ACopyFunc;
FTimesheet := ATimesheet;
end;

procedure TDbCustomTimesheetEntry.CreateCalcFields;
begin
inherited;
FClockable := CreateCalcBooleanField(k_Clockable);
FClockableHours := CreateCalcFloatField(k_ClockableHours);
FDayOfWeek := CreateCalcStringField(k_WeekDay, 13);
FDifference := CreateCalcFloatField(k_Difference);
FEmployeeName := CreateCalcStringField(k_EmployeeName, 40);
FEntryTypeCaption := CreateCalcStringField(k_EntryTypeCaption, 20);
FFiscalYearEndDate := CreateCalcDateTimeField(k_FiscalYearEndDate);
FFiscalYearStartDate := CreateCalcDateTimeField(k_FiscalYearStartDate);
FScheduledTimeIn := CreateCalcDateTimeField(k_ScheduledTimeIn);
FScheduledTimeOut := CreateCalcDateTimeField(k_ScheduledTimeOut);
FTimeElapsed := CreateCalcFloatField(k_TimeElapsed);
FTimeScheduled := CreateCalcFloatField(k_TimeScheduled);
FWeekOf := CreateCalcDateTimeField(k_WeekOf);
end;

procedure TDbCustomTimesheetEntry.CreateFields;
begin
FID := CreateField(k_Id);
FEmployeeID := CreateField(k_EmployeeID);
FEntryTypeID := CreateField(k_EntryTypeID);
FRowNbr := CreateField(k_RowNbr);
FTimeIn := CreateField(k_TimeIn);
FTimeOut := CreateField(k_TimeOut);
FID := CreateField(k_ID);
FDateIn := CreateField(k_DateIn);
FDateOut := CreateField(k_DateOut);
FCreatedBy := CreateField(k_CreatedBy);
FCreatedTimestamp := CreateField(k_CreatedTimeStamp);
FLastModifiedBy := CreateField(k_LastModifiedBy);
FLastModifiedTimestamp := CreateField(k_LastModifiedTimestamp);
FNote := CreateField(k_Note);
FPayPeriodEndDate := CreateField(k_PayPeriodEndDate);

end;

procedure TDbCustomTimesheetEntry.CreateIndexes;
const
FIELD_LIST = k_DateIn + ';' + k_RowNbr;
begin
inherited;
FDateIndex := CreateIndex('ByDate', FIELD_LIST);
FDateIndex.Selected := True;
Dataset.IndexesActive := True;
end;

function TDbCustomTimesheetEntry.GetClockable: Boolean;
begin
Result := Rules.Clockable;
end;

function TDbCustomTimesheetEntry.GetClockableHours: THours;
begin
Result := Rules.ClockableHours;
end;

function TDbCustomTimesheetEntry.GetCreatedBy: TUserName;
begin
Result := FCreatedBy.AsUserName;
end;

function TDbCustomTimesheetEntry.GetCreatedTimestamp: TDateTime;
begin
Result := FCreatedTimestamp.AsDateTime;
end;

function TDbCustomTimesheetEntry.GetDateIn: TDate;
begin
Result := FDateIn.AsDateTime;
end;

function TDbCustomTimesheetEntry.GetDateOut: TDate;
begin
Result := FDateOut.AsDateTime;
end;

function TDbCustomTimesheetEntry.GetDifference: THours;
begin
Result := Rules.Difference;
end;

function TDbCustomTimesheetEntry.GetEmployeeID: TIdentifier;
begin
Result := FEmployeeID.AsIdentifier;
end;

function TDbCustomTimesheetEntry.GetEmployeeName: string;
begin
Result := Rules.EmployeeName;
end;

function TDbCustomTimesheetEntry.GetEntryTypeID: TIdentifier;
begin
Result := FEntryTypeID.AsIdentifier;
end;

function TDbCustomTimesheetEntry.GetFiscalYearEndDate: TDate;
begin
Result := FFiscalYearEndDate.AsDateTime;
end;

function TDbCustomTimesheetEntry.GetFiscalYearStartDate: TDate;
begin
Result := FFiscalYearStartDate.AsDateTime;
end;

function TDbCustomTimesheetEntry.GetHasEntries: Boolean;
begin
Result := RecordCount > 0;
end;

function TDbCustomTimesheetEntry.GetID: TIdentifier;
begin
Result := FID.AsInteger;
end;

function TDbCustomTimesheetEntry.GetLastModifiedBy: TUserName;
begin
Result := FLastModifiedBy.AsUserName;
end;

function TDbCustomTimesheetEntry.GetLastModifiedTimestamp: TDateTime;
begin
Result := FLastModifiedTimestamp.AsDateTime;
end;

function TDbCustomTimesheetEntry.GetModel: ITimesheetEntry;
var
LResult: ITimesheetEntry;
begin
LResult := FCopyFunc(Self);
Result := LResult;
end;

function TDbCustomTimesheetEntry.GetNote: AnsiString;
begin
Result := FNote.AsAnsiString;
end;

function TDbCustomTimesheetEntry.GetPayPeriodEndDate: TDate;
begin
Result := FPayPeriodEndDate.AsDateTime;
end;

function TDbCustomTimesheetEntry.GetPlaceholder: Boolean;
begin
Result := Rules.Placeholder;
end;

function TDbCustomTimesheetEntry.GetEntry: ITimesheetEntry;
begin
Result := Model;
end;

function TDbCustomTimesheetEntry.GetEntryTypeCaption: TCaption;
begin
Result := Rules.EntryTypeCaption
end;

function TDbCustomTimesheetEntry.GetRowNbr: TRowNbr;
begin
Result := FRowNbr.AsRowNbr;
end;

function TDbCustomTimesheetEntry.GetScheduledTimeIn: TTime;
begin
Result := Rules.ScheduledTimeIn;
end;

function TDbCustomTimesheetEntry.GetScheduledTimeOut: TTime;
begin
Result := Rules.ScheduledTimeOut;
end;

function TDbCustomTimesheetEntry.GetTimeElapsed: THours;
begin
Result := Rules.TimeElapsed;
end;

function TDbCustomTimesheetEntry.GetTimein: TTime;
begin
Result := FTimeIn.AsDateTime;
end;

function TDbCustomTimesheetEntry.GetTimeOut: TTime;
begin
Result := FTimeOut.AsDateTime;
end;

function TDbCustomTimesheetEntry.GetTimeScheduled: THours;
begin
Result := Rules.TimeScheduled;
end;

function TDbCustomTimesheetEntry.GetTimesheet: ITimesheet;
begin
Result := FTimesheet;
end;

function TDbCustomTimesheetEntry.GetWeekDay: string;
begin
Result := Rules.WeekDay;
end;

function TDbCustomTimesheetEntry.GetWeekOf: TDate;
begin
Result := Rules.WeekOf;
end;

procedure TDbCustomTimesheetEntry.Load;
begin
//Stub procedure
end;

procedure TDbCustomTimesheetEntry.OnCalcFields(Dataset: TDataset);
begin
inherited;
if not Assigned(Rules) then Exit;

FClockable.AsBoolean := GetClockable;
FClockableHours.AsHours := GetClockableHours;
FDayOfWeek.AsString := GetWeekDay;
FDifference.AsHours := GetDifference;
FEmployeeName.AsString := GetEmployeeName;
FEntryTypeCaption.AsCaption := GetEntryTypeCaption;
FTimeElapsed.AsHours := GetTimeElapsed;
FTimeScheduled.AsHours := GetTimeScheduled;
FScheduledTimeIn.AsDateTime := GetScheduledTimeIn;
FScheduledTimeOut.AsDateTime := GetScheduledTimeOut;
FWeekOf.AsDateTime := GetWeekOf;
end;

procedure TDbCustomTimesheetEntry.OnNewRecord(Dataset: TDataset);
begin
inherited;

FEmployeeID.AsIdentifier := FTimesheet.EmployeeID;
FFiscalYearEndDate.AsDateTime := FTimesheet.FiscalYearEndDate;
FFiscalYearStartDate.AsDateTime := FTimesheet.FiscalYearStartDate;
FPayPeriodEndDate.AsDateTime := FTimesheet.PayPeriodEndDate;
end;

procedure TDbCustomTimesheetEntry.DoUpdate(AModel: ITimesheetEntry);
begin
inherited;

FEmployeeID.AsIdentifier := AModel.EmployeeID;
FRowNbr.AsRowNbr := AModel.RowNbr;
FEntryTypeID.AsIdentifier := AModel.EntryTypeID;
FDateIn.AsDateTime := AModel.DateIn;
FTimeIn.AsDateTime := AModel.TimeIn;
FDateOut.AsDateTime := AModel.DateOut;
FTimeOut.AsDateTime := AModel.TimeOut;
FNote.AsAnsiString := AModel.Note;
end;

procedure TDbCustomTimesheetEntry.FilterEntries(const ADate: TDate);
begin
FDateIndex.Selected := True;
SetRange([ADate], [ADate]);
end;

function TDbCustomTimesheetEntry.Find(AModel: ITimesheetEntry): Boolean;
begin
Result := Locate(k_ID, AModel.ID);
end;

procedure TDbCustomTimesheetEntry.FormatFields;
begin
inherited;
FTimeElapsed.OnGetText := HoursFieldGetText;
FClockableHours.OnGetText := HoursFieldGetText;
FDifference.OnGetText := HoursFieldGetText;
FTimeScheduled.OnGetText := HoursFieldGetText;

SetTimeFieldDisplayFormat(FTimeIn);
SetTimeFieldDisplayFormat(FTimeOut);
SetDateFieldDisplayFormat(FDateIn);
SetDateFieldDisplayFormat(FDateOut);
SetDateFieldDisplayFormat(FPayPeriodEndDate);
SetSQLTimestampFieldDisplayFormat(FCreatedTimestamp);
SetSQLTimestampFieldDisplayFormat(FLastModifiedTimestamp);
end;

{ TDbDummyEntry }

procedure TDbSourceEntry.BeforePost(Dataset: TDataset);
var
LTimestamp: TDateTime;
begin
inherited;
LTimestamp := Now;
FLastModifiedBy.AsUserName := FTimesheet.User.UserName;
FLastModifiedTimestamp.AsDateTime := LTimestamp;
if State in [dsInsert] then
begin
FCreatedBy.AsUserName := FTimesheet.User.UserName;
FCreatedTimestamp.AsDateTime := LTimestamp;
end;
end;

constructor TDbSourceEntry.Create(ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>; ATimesheet: ITimesheet;
ACopyFunc: TCopyFunc<ITimesheetEntry>; AProc: TLoadTimesheetProc;
AElectionList: ILevelPayElectionList; APositionList: IHourlyPositionList;
ACreateFields: Boolean);
begin
inherited Create(ADataset, AModelFunc, ACopyFunc, ATimesheet, ACreateFields);

FLoadTimesheetEntries := AProc;
FElectionList := AElectionList;
FPositionList := APositionList;
end;

procedure TDbSourceEntry.Load;
var
LEmployeeID: TIdentifier;
LFirstEntryDate: TDate;
LLastEntryDate: TDate;
begin
LEmployeeID := FTimesheet.EmployeeID;
LFirstEntryDate := FTimesheet.FirstEntryDate;
LLastEntryDate := FTimesheet.LastEntryDate;
FLoadTimesheetEntries(LEmployeeID, LFirstEntryDate, LLastEntryDate);
end;


{ TDbDummyEntry }

procedure TDbDummyEntry.AddPlacedholder(ADate: TDate; ARowNbr: TRowNbr);
var
LEntryTypeID: TIdentifier;
LClosure: ISchoolClosure;
LNote: AnsiString;
LRowNbr: TRowNbr;
begin
Dec(FPlaceholderID);
LNote := '';
LEntryTypeID := 0;
LRowNbr := ARowNbr;

if LRowNbr < 2 then //This is a first entry for the date
begin
if FClosureList.Find(ADate) then
begin
LClosure := FClosureList.Closure;
LEntryTypeID := LClosure.EntryTypeID;
LNote := AnsiString(LClosure.Caption);
end
else
begin
if TDateTime(ADate).DayOfWeek in [MONDAY..FRIDAY] then
LEntryTypeID := k_Regular
else
LEntryTypeID := 0;
end;
end;

Append;
FId.AsIdentifier := FPlaceholderID;
FRowNbr.AsRowNbr := LRowNbr;
FDateIn.AsDateTime := ADate;
FDateOut.AsDateTime := ADate;
FEntryTypeID.AsIdentifier := LEntryTypeID;
FNote.AsAnsiString := LNote;
Post;
end;

constructor TDbDummyEntry.Create(ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>; ACopyFunc: TCopyFunc<ITimesheetEntry>;
ATimesheet: ITimesheet; AClosureList: ISchoolClosureList; ACreateFields: Boolean);
begin
inherited Create(ADataset, AModelFunc, ACopyFunc, ATimesheet, ACreateFields);
FClosureList := AClosureList;
end;

procedure TDbDummyEntry.CreateFields;
begin
inherited;
FId.ReadOnly := False;
FId.AutoGenerateValue := arNone;
FEntryTypeID.OnChange := EntryTypeIDOnChange;
end;

procedure TDbDummyEntry.DoAdd(AModel: ITimesheetEntry);
begin
inherited;
FId.AsIdentifier := AModel.ID;
end;

procedure TDbDummyEntry.EntryTypeIDOnChange(Sender: TField);
var
LDateIn: TDate;
LDateOut: TDate;
begin
if Sender.AsIdentifier = k_LandSchool then
begin
LDateIn := FDateIn.AsDateTime;
LDateOut := LDateIn + 1;
FDateOut.AsDateTime := LDateOut;
FTimeIn.AsDateTime := GetScheduledTimeOut;
FTimeOut.AsDateTime := GetScheduledTimeIn;
end;
end;

{ TDbTimesheetEntry }

procedure TDbTimesheetEntry.Add(AModel: ITimesheetEntry);
var
LEntry: ITimesheetEntry;
begin
FSource.Add(AModel);
LEntry := FSource.Entry; //Get model with updated ID
FTimesheet.WorkweekList.AddEntry(LEntry);
inherited Add(LEntry);
end;

procedure TDbTimesheetEntry.Clear;
begin
PlaceholderID := 0;
Dataset.CancelUpdates;
DisableControls;
try
First;
while RecordCount > 0 do
Dataset.Delete;
finally
EnableControls;
end;
end;

constructor TDbTimesheetEntry.Create(ADataset: TFDDataset;
AModelFunc: TModelFunc<ITimesheetEntry>;
ACopyFunc: TCopyFunc<ITimesheetEntry>; ATimesheet: ITimesheet;
ASourceFunc: TSourceListFunc; AClosureList: ISchoolClosureList;
ACreateFields: Boolean);
begin
inherited Create(ADataset, AModelFunc, ACopyFunc, ATimesheet, AClosureList, ACreateFields);
FSource := ASourceFunc(FTimesheet);

FClone := TFDMemTable.Create(ADataset);
FClone.CloneCursor(ADataset);
end;

procedure TDbTimesheetEntry.Delete(AModel: ITimesheetEntry);
var
LDate: TDate;
LRowNbr: SmallInt;
LEntry: ITimesheetEntry;
begin
FSource.Delete(AModel);
WorkweekList.DeleteEntry(AModel);
DisableControls;
try
LDate := AModel.DateIn;
LRowNbr := AModel.RowNbr;
inherited Delete(AModel);
if (LRowNbr = 1) then
begin
AddPlacedholder(LDate, 0);
LEntry := Model; //Get placeholder
WorkweekList.AddEntry(LEntry);
end;
finally
EnableControls;
end;
end;

function TDbTimesheetEntry.GetNextRowNbr: TRowNbr;
begin
Result := 0;
FClone.SetRange([GetDateIn], [GetDateIn]);
while not FClone.Eof do
begin
Result := FClone.FieldByName(k_RowNbr).AsRowNbr + 1;
FClone.Next;
end;
FClone.CancelRange;
end;

procedure TDbTimesheetEntry.Load;
var
LDate: TDate;
LFirstEntryDate: TDate;
LCutoffDate: TDate;
LEntry: ITimesheetEntry;
LWeekOf: TDate;
LWorkweekList: IWorkweekList;
begin
LWorkweekList := FTimesheet.WorkweekList;
LFirstEntryDate := FTimesheet.FirstEntryDate;
LCutOffDate := FTimesheet.LastEntryDate;
LWeekOf := TDateTime(LFirstEntryDate).StartOfWeek;

LWorkweekList.Init(LFirstEntryDate, LCutOffDate);
FSource.Load;
DisableControls;
try
Clear;

LDate := LWeekOf;
repeat
FSource.FilterEntries(LDate);
if FSource.HasEntries then
begin
for LEntry in FSource do
begin
if LDate >= LFirstEntryDate then
begin
inherited Add(LEntry); //this must call inherited add to adding to FSource
end;
LWorkweekList.AddEntry(LEntry);
end;
end
else
begin
if LDate >= LFirstEntryDate then
begin
AddPlacedholder(LDate, 0);
LEntry := GetModel; //This retrieves the placeholder
LWorkweekList.AddEntry(LEntry);
end;
end;
LDate := LDate + 1;
until LDate > LCutOffDate;
finally
FSource.ClearFilter;
EnableControls;
First;
end;
end;

procedure TDbTimesheetEntry.Update(OldModel, NewModel: ITimesheetEntry);
var
LEntry: ITimesheetEntry;
begin
DisableControls;
try
if Assigned(OldModel) then
begin
if OldModel.Placeholder then
begin
FSource.Add(NewModel);
end
else
begin
FSource.Update(NewModel);
end;
inherited Delete(OldModel);
WorkweekList.DeleteEntry(OldModel);
end
else
begin
FSource.Add(NewModel);
end;

LEntry := FSource.Entry; //Get entry with new ID
inherited Add(LEntry);
WorkweekList.AddEntry(LEntry);
finally
EnableControls;
end;
end;

function TDbTimesheetEntry.WorkweekList: IWorkweekList;
begin
Result := FTimesheet.WorkweekList;
end;

end.

最佳答案

一般来说,当你有很多构造函数参数(这意味着依赖)时,这表明你的类可能做的太多了(参见单一责任原则)。

如果某些依赖项大部分时间只相互交互,这表明这些依赖项可能会被重构为它们自己的组件/类,然后注入(inject)。这不仅首先减少了依赖关系,而且降低了组件的复杂性。

我建议阅读 Mark Seemann 的博客,他解释了正确实践依赖注入(inject)和软件设计和架构的许多领域。

我只记得两个例子:

  • http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/
  • http://blog.ploeh.dk/2018/08/27/on-constructor-over-injection/
  • 关于delphi - 构造函数依赖注入(inject)替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53279936/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com