5

好的,我已经搜索并找不到适合我的问题的解决方案,我正在重新设计我们销售点系统的一部分。假设我们有以下类:

TWorkShift = class
   Date: TDateTime;
   fTotalSold: Currency;
   fSales: TList<TSale>; 
public
   property TotalSold: Currency read fTotalSold write fTotalSold;
   property Sales: Currency read fSales write fSales;
end;

TSale = class
    fAmount: Currency;
    fWorkShift: TWorkShift;
public
    property Amount: Currency read fAmount write fAmount; 
    procedure Save;  
end;

现在,我面临的问题是试图在不违反得墨忒耳法则的情况下得出最好的主意。我想要完成的是以下内容:

  1. 每次保存新的 TSale 时,我都想将其添加到当前用户的 TWorkShift 的销售列表中,并且我想将销售金额与 TWorkShift 的“TotalSold”相加。

我尝试了两种不同的方法:

方法一:

// 假设我们有一个 ID 为 1 的工作班次,并从数据库中加载: CurrentShift := TWorkShift.Create(1);

NewSale := TSale.Create;
NewSale.Amount:=100;
NewSale.Save;

CurrentShift.Sales.Add(NewSale);
CurrentShift.TotalSold := CurrentShift.TotalSold + NewSale.Amount;

这种方法的问题在于它很难测试,因为我想将求和的逻辑封装在某些类或其他地方(可能是一个新类?)。

方法 B:

我的另一种方法是将该代码包含在 TSale 类本身中:

procedure TSale.Save;
begin
    SaveToDataBase; 

    fWorkShift.Sales.Add(Self);
    fWorkShift.TotalSold := fWorkShift.TotalSold + Self.Amount;
end;

我认为这种方法违反了得墨忒耳法则,我觉得不对。

我想找到一种“正确的方法”来最大限度地简化代码并在未来易于维护。因此,任何建议将不胜感激。

谢谢

4

2 回答 2

3

如果您想向 TWorkShift 添加销售,那么您应该

TWorkShift.AddSale(aSale: TSale);
begin
  Sales.Add(aSale);
end;

换句话说,TWorkShift 应该“要求”它需要的东西。

此外,我看不出 TSale 会有 TWorkShift 字段的任何理由。Workshift 有很多销售,但为什么 Sale 会有 WorkShift?

于 2012-04-26T23:38:07.220 回答
0

当您将项目添加到 TList 时,您正在做一些事情,以便您可以使用 OnNotify。我不知道 Aurelius 是否也在使用该事件,所以我为此添加了一些代码。您只需要在将列表分配给 TWorkShift 对象后查看是否可以在框架内分配 OnNotify,因为那样它可能会覆盖 NotifySales 事件处理程序。

type
  TWorkShift = class
  private
    Date: TDateTime;
    fTotalSold: Currency;
    fSales: TList<TSale>;
    fNotifySales: TCollectionNotifyEvent<TSale>;
    procedure NotifySales(Sender: TObject; const Item: TSale;
      Action: TCollectionNotification);
    procedure SetSales(const Value: TList<TSale>);
  public
    property TotalSold: Currency read fTotalSold write fTotalSold;
    property Sales: TList<TSale> read fSales write SetSales;
  end;

procedure TWorkShift.NotifySales(Sender: TObject; const Item: TSale;
  Action: TCollectionNotification);
begin
  if Assigned(fNotifySales) then
    fNotifySales(Sender, Item, Action);

  case Action of
    cnAdded: fTotalSold := fTotalSold + Item.Amount;
    cnRemoved: fTotalSold := fTotalSold - Item.Amount;
  end;
end;

procedure TWorkShift.SetSales(const Value: TList<TSale>);
begin
  if Assigned(fSales) then
  begin
    fSales.OnNotify := fNotifySales;
    fNotifySales := nil;
  end;

  fSales := Value;

  if Assigned(fSales) then
  begin
    fNotifySales := fSales.OnNotify;
    fSales.OnNotify := NotifySales;
  end;
end;
于 2012-04-27T09:23:43.850 回答