Cart.pas
unit UnitCart;
interface
uses
System.Generics.Collections,
UnitList,
UnitFood,
UnitIDiscount;
type
Cart = class
private
var foods:TList<Food>;
public
constructor Create();
destructor Destroy(); override;
procedure add(_food:Food);
function getTotalPrice():integer; overload;
function getTotalPrice(discount:IDiscount):integer; overload;
function getList(_list:List):string;
function getFoods():TList<Food>;
end;
implementation
constructor Cart.Create();
begin
foods := TList<Food>.Create();
end;
destructor Cart.Destroy();
var _food:Food;
begin
for _food in foods do begin
_food.Free;
end;
foods.Free;
inherited Destroy();
end;
procedure Cart.add(_food:Food);
begin
foods.Add(_food);
end;
function Cart.getTotalPrice():integer;
var sum:integer;
var _food:Food;
begin
sum := 0;
for _food in foods do begin
sum := sum + _food.getPrice();
end;
Result := sum;
end;
function Cart.getTotalPrice(discount:IDiscount):integer;
var sum:integer;
var _food:Food;
begin
sum := 0;
for _food in foods do begin
sum := sum + discount.getPrice(_food);
end;
Result := sum;
end;
function Cart.getList(_list:List):string;
begin
Result := _list.getList(foods);
end;
function Cart.getFoods():TList<Food>;
begin
Result := foods;
end;
end.
CmdCalculate.pas
unit UnitCmdCalculate;
interface
uses
System.Generics.Collections,
System.RegularExpressions,
System.SysUtils,
UnitCommand,
UnitExpression,
UnitFood,
UnitOperator,
UnitOperationAdd,
UnitCurrency,
UnitIngredient,
UnitVegetable,
UnitMeat,
UnitOperationMultiply,
UnitOperationDivide;
type
CmdCalculate = class(Command)
private
const CRLF = #13#10;
var ex:Expression;
public
destructor Destroy(); override;
procedure execute(); override;
function calc(_food:Food):Operator;
end;
implementation
destructor CmdCalculate.Destroy();
begin
ex.Free;
end;
procedure CmdCalculate.execute();
var _food:Food;
var foods:TList<Food>;
begin
ex := Expression.Create();
foods := _cart.getFoods();
for _food in foods do begin
ex := Expression.Create(OperationAdd.Create(ex, Expression.Create(calc(_food))));
end;
_register.appendInfo('合計金額 ' + Currency.displayComma(Trunc(ex.getOperand())) + CRLF);
end;
function CmdCalculate.calc(_food:Food):Operator;
var price, quantity:Ingredient;
var str:string;
var vol:double;
var volume, per:Ingredient;
begin
price := Ingredient.Create(_food.getUnitPrice());
if _food is Vegetable then begin
quantity := Ingredient.Create((_food as Vegetable).getQuantity());
Result := OperationMultiply.Create(price, quantity);
end
else begin
str := TRegEx.Replace((_food as Meat).getVolume(), '[^+\-0-9\.]', '');
vol := StrToFloat(str);
volume := Ingredient.Create(vol);
per := Ingredient.Create(100.0);
Result := OperationMultiply.Create(price, Expression.Create(OperationDivide.Create(volume, per)));
end;
end;
end.
IOperand.pas
unit UnitIOperand;
interface
type
IOperand = interface
function getOperand():double;
end;
implementation
end.
Expression.pas
unit UnitExpression;
interface
uses
UnitIOperand,
UnitOperator,
UnitIngredient,
UnitOperationAdd;
type
Expression = class(TInterfacedObject, IOperand)
private
var _operator:Operator;
public
constructor Create(); overload;
constructor Create(_operator:Operator); overload;
destructor Destroy(); override;
function getOperand():double;
end;
implementation
constructor Expression.Create();
var zero:IOperand;
begin
zero := Ingredient.Create(0);
_operator := OperationAdd.Create(zero, zero);
end;
constructor Expression.Create(_operator:Operator);
begin
self._operator := _operator;
end;
destructor Expression.Destroy();
begin
_operator.Free;
end;
function Expression.getOperand():double;
begin
Result := _operator.execute().getOperand();
end;
end.
Ingredient.pas
unit UnitIngredient;
interface
uses
UnitIOperand;
type
Ingredient = class(TInterfacedObject, IOperand)
private
var operand:double;
public
constructor Create(operand:double);
function getOperand():double;
end;
implementation
constructor Ingredient.Create(operand:double);
begin
self.operand := operand;
end;
function Ingredient.getOperand():double;
begin
Result := operand;
end;
end.
Operator.pas
unit UnitOperator;
interface
uses
UnitIOperand,
UnitIngredient;
type
Operator = class
protected
var operand1, operand2:IOperand;
public
constructor Create(operand1:IOperand; operand2:IOperand);
function execute():IOperand; virtual; abstract;
end;
implementation
constructor Operator.Create(operand1:IOperand; operand2:IOperand);
begin
self.operand1 := operand1;
self.operand2 := operand2;
end;
end.
OperationAdd.pas
unit UnitOperationAdd;
interface
uses
UnitOperator,
UnitIOperand,
UnitIngredient;
type
OperationAdd = class(Operator)
public
constructor Create(operand1:IOperand; operand2:IOperand);
function execute():IOperand; override;
end;
implementation
constructor OperationAdd.Create(operand1:IOperand; operand2:IOperand);
begin
inherited Create(operand1, operand2);
end;
function OperationAdd.execute():IOperand;
begin
Result := Ingredient.Create(operand1.getOperand() + operand2.getOperand());
end;
end.
OperationSubtract.pas
unit UnitOperationSubtract;
interface
uses
UnitOperator,
UnitIOperand,
UnitIngredient;
type
OperationSubtract = class(Operator)
public
constructor Create(operand1:IOperand; operand2:IOperand);
function execute():IOperand; override;
end;
implementation
constructor OperationSubtract.Create(operand1:IOperand; operand2:IOperand);
begin
inherited Create(operand1, operand2);
end;
function OperationSubtract.execute():IOperand;
begin
Result := Ingredient.Create(operand1.getOperand() - operand2.getOperand());
end;
end.
OperationMultiply.pas
unit UnitOperationMultiply;
interface
uses
UnitOperator,
UnitIOperand,
UnitIngredient;
type
OperationMultiply = class(Operator)
public
constructor Create(operand1:IOperand; operand2:IOperand);
function execute():IOperand; override;
end;
implementation
constructor OperationMultiply.Create(operand1:IOperand; operand2:IOperand);
begin
inherited Create(operand1, operand2);
end;
function OperationMultiply.execute():IOperand;
begin
Result := Ingredient.Create(operand1.getOperand() * operand2.getOperand());
end;
end.
OperationDivide.pas
unit UnitOperationDivide;
interface
uses
UnitOperator,
UnitIOperand,
UnitIngredient;
type
OperationDivide = class(Operator)
public
constructor Create(operand1:IOperand; operand2:IOperand);
function execute():IOperand; override;
end;
implementation
constructor OperationDivide.Create(operand1:IOperand; operand2:IOperand);
begin
inherited Create(operand1, operand2);
end;
function OperationDivide.execute():IOperand;
begin
Result := Ingredient.Create(operand1.getOperand() / operand2.getOperand());
end;
end.