D
degann
Unregistered / Unconfirmed
GUEST, unregistred user!
策略(Strategy)模式的用意是定义一组算法(algorithms),
并将每个算法封装到具有共同接口的独立的类中,从而使它们可以相互替换。
策略模式让算法变化独立于使用它的客户端。
unit HotelSaleStrategy;
interface
type
TSaleStrategy = class(TObject)
public
function SalePrice(Price: Currency
Value: Integer): Currency
virtual
abstract;
end;
TSeasonStrategy = class(TSaleStrategy)
public
function SalePrice(Price: Currency
Value: Integer): Currency
override;
end;
TVIPStrategy = class(TSaleStrategy)
public
function SalePrice(Price: Currency
Value: Integer): Currency
override;
end;
TTeamStrategy = class(TSaleStrategy)
public
function SalePrice(Price: Currency
Value: Integer): Currency
override;
end;
TPriceContext = class(TObject)
private
FStrategy: TSaleStrategy;
procedure SetStrategy(Value: TSaleStrategy);
public
function GetPrice(Price: Currency
Value: Integer): Currency;
property Strategy: TSaleStrategy read FStrategy write SetStrategy;
end;
implementation
{TSeasonStrategy}
function TSeasonStrategy.SalePrice(Price: Currency
Value: Integer): Currency;
begin
//季節銷售策略
{
2, 3, 11月8.5折優惠
4, 6月9折優惠
8, 9月9.5折優惠
}
case Value of
2, 3, 11: Result := Price * 0.85;
4, 6: Result := Price * 0.9;
8, 9: Result := Price * 0.95;
else
Result := Price;
end;
end;
{TVIPStrategy}
function TVIPStrategy.SalePrice(Price: Currency
Value: Integer): Currency;
begin
//VIP卡銷售策略
{
0: VIP銀卡 9折優惠
1: VIP金卡 8折優惠
2: VIP鑽石卡 7折優惠
}
case Value of
0: Result := Price * 9;
1: Result := Price * 8;
2: Result := Price * 7
end;
end;
{TTeamStrategy}
function TTeamStrategy.SalePrice(Price: Currency
Value: Integer): Currency;
begin
//團隊銷售策略
{
3-5人團隊9折優惠
6-10人團隊8折優惠
11-20人團隊7折優惠
20人以上團隊6折優惠
}
Result := Price;
if (Value < 6) and (Value > 2) then Result := Price * 0.9 else
if (Value < 11) and (Value >5) then Result := Price * 0.8 else
if (Value < 21) and (Value > 10) then Result := Price * 0.7 else
if Value > 20 then Result := Price * 0.6;
end;
{TPriceContext}
function TPriceContext.GetPrice(Price: Currency
Value: Integer): Currency;
begin
Result := Strategy.SalePrice(Price, Value);
end;
procedure TPriceContext.SetStrategy(Value: TSaleStrategy);
begin
FStrategy := Value;
end;
end.
unit ClientForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, HotelSaleStrategy, StdCtrls, ComCtrls, ExtCtrls, DateUtils;
type
TClient = class(TForm)
RadioGroup1: TRadioGroup;
dtpDate: TDateTimePicker;
cmbVIP: TComboBox;
edtCount: TEdit;
cmbPrice: TComboBox;
btnCheck: TButton;
edtPrice: TEdit;
btnExit: TButton;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Bevel1: TBevel;
procedure RadioGroup1Click(Sender: TObject);
procedure btnCheckClick(Sender: TObject);
procedure btnExitClick(Sender: TObject);
private
FSeasonStrategy: TSaleStrategy;
FVIPStrategy: TSaleStrategy;
FTeamStrategy: TSaleStrategy;
FPriceSys: TPriceContext;
end;
var
Client: TClient;
implementation
{$R *.dfm}
procedure TClient.RadioGroup1Click(Sender: TObject);
begin
dtpDate.Enabled := False;
cmbVIP.Enabled := False;
edtCount.Enabled := False;
Case RadioGroup1.ItemIndex of
0: dtpDate.Enabled := True;
1: cmbVIp.Enabled := True;
2: edtCount.Enabled := True;
end;
end;
(*$WARNINGS OFF*)
procedure TClient.btnCheckClick(Sender: TObject);
var
I: Integer;
Price: Currency;
begin
try
FSeasonStrategy := TSeasonStrategy.Create;
FVIPStrategy := TVIPStrategy.Create;
FTeamStrategy := TTeamStrategy.Create;
FPriceSys := TPriceContext.Create;
case RadioGroup1.ItemIndex of
0: begin
FPriceSys.Strategy := FSeasonStrategy;
I := MonthOf(dtpDate.DateTime);
end;
1: begin
FPriceSys.Strategy := FVIPStrategy;
I := cmbVIP.ItemIndex;
end;
2: begin
FPriceSys.Strategy := FTeamStrategy;
I := StrToInt(edtCount.Text);
end;
end;
case cmbPrice.ItemIndex of
0: Price := 300;//甲類標准間300元
1: Price := 500;//乙類標准間500元
2: Price := 800;//貴賓間800元
3: Price := 1000;//商務套房1000元
4: Price := 2000;//豪華套房2000元
end;
edtPrice.Text := CurrToStr(FPriceSys.GetPrice(Price, I));
finally
FSeasonStrategy.Free;
FVIPStrategy.Free;
FTeamStrategy.Free;
FPriceSys.Free;
end;
end;
(*$WARNINGS ON*)
procedure TClient.btnExitClick(Sender: TObject);
begin
Close;
end;
end.
并将每个算法封装到具有共同接口的独立的类中,从而使它们可以相互替换。
策略模式让算法变化独立于使用它的客户端。
unit HotelSaleStrategy;
interface
type
TSaleStrategy = class(TObject)
public
function SalePrice(Price: Currency
Value: Integer): Currency
virtual
abstract;
end;
TSeasonStrategy = class(TSaleStrategy)
public
function SalePrice(Price: Currency
Value: Integer): Currency
override;
end;
TVIPStrategy = class(TSaleStrategy)
public
function SalePrice(Price: Currency
Value: Integer): Currency
override;
end;
TTeamStrategy = class(TSaleStrategy)
public
function SalePrice(Price: Currency
Value: Integer): Currency
override;
end;
TPriceContext = class(TObject)
private
FStrategy: TSaleStrategy;
procedure SetStrategy(Value: TSaleStrategy);
public
function GetPrice(Price: Currency
Value: Integer): Currency;
property Strategy: TSaleStrategy read FStrategy write SetStrategy;
end;
implementation
{TSeasonStrategy}
function TSeasonStrategy.SalePrice(Price: Currency
Value: Integer): Currency;
begin
//季節銷售策略
{
2, 3, 11月8.5折優惠
4, 6月9折優惠
8, 9月9.5折優惠
}
case Value of
2, 3, 11: Result := Price * 0.85;
4, 6: Result := Price * 0.9;
8, 9: Result := Price * 0.95;
else
Result := Price;
end;
end;
{TVIPStrategy}
function TVIPStrategy.SalePrice(Price: Currency
Value: Integer): Currency;
begin
//VIP卡銷售策略
{
0: VIP銀卡 9折優惠
1: VIP金卡 8折優惠
2: VIP鑽石卡 7折優惠
}
case Value of
0: Result := Price * 9;
1: Result := Price * 8;
2: Result := Price * 7
end;
end;
{TTeamStrategy}
function TTeamStrategy.SalePrice(Price: Currency
Value: Integer): Currency;
begin
//團隊銷售策略
{
3-5人團隊9折優惠
6-10人團隊8折優惠
11-20人團隊7折優惠
20人以上團隊6折優惠
}
Result := Price;
if (Value < 6) and (Value > 2) then Result := Price * 0.9 else
if (Value < 11) and (Value >5) then Result := Price * 0.8 else
if (Value < 21) and (Value > 10) then Result := Price * 0.7 else
if Value > 20 then Result := Price * 0.6;
end;
{TPriceContext}
function TPriceContext.GetPrice(Price: Currency
Value: Integer): Currency;
begin
Result := Strategy.SalePrice(Price, Value);
end;
procedure TPriceContext.SetStrategy(Value: TSaleStrategy);
begin
FStrategy := Value;
end;
end.
unit ClientForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, HotelSaleStrategy, StdCtrls, ComCtrls, ExtCtrls, DateUtils;
type
TClient = class(TForm)
RadioGroup1: TRadioGroup;
dtpDate: TDateTimePicker;
cmbVIP: TComboBox;
edtCount: TEdit;
cmbPrice: TComboBox;
btnCheck: TButton;
edtPrice: TEdit;
btnExit: TButton;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Bevel1: TBevel;
procedure RadioGroup1Click(Sender: TObject);
procedure btnCheckClick(Sender: TObject);
procedure btnExitClick(Sender: TObject);
private
FSeasonStrategy: TSaleStrategy;
FVIPStrategy: TSaleStrategy;
FTeamStrategy: TSaleStrategy;
FPriceSys: TPriceContext;
end;
var
Client: TClient;
implementation
{$R *.dfm}
procedure TClient.RadioGroup1Click(Sender: TObject);
begin
dtpDate.Enabled := False;
cmbVIP.Enabled := False;
edtCount.Enabled := False;
Case RadioGroup1.ItemIndex of
0: dtpDate.Enabled := True;
1: cmbVIp.Enabled := True;
2: edtCount.Enabled := True;
end;
end;
(*$WARNINGS OFF*)
procedure TClient.btnCheckClick(Sender: TObject);
var
I: Integer;
Price: Currency;
begin
try
FSeasonStrategy := TSeasonStrategy.Create;
FVIPStrategy := TVIPStrategy.Create;
FTeamStrategy := TTeamStrategy.Create;
FPriceSys := TPriceContext.Create;
case RadioGroup1.ItemIndex of
0: begin
FPriceSys.Strategy := FSeasonStrategy;
I := MonthOf(dtpDate.DateTime);
end;
1: begin
FPriceSys.Strategy := FVIPStrategy;
I := cmbVIP.ItemIndex;
end;
2: begin
FPriceSys.Strategy := FTeamStrategy;
I := StrToInt(edtCount.Text);
end;
end;
case cmbPrice.ItemIndex of
0: Price := 300;//甲類標准間300元
1: Price := 500;//乙類標准間500元
2: Price := 800;//貴賓間800元
3: Price := 1000;//商務套房1000元
4: Price := 2000;//豪華套房2000元
end;
edtPrice.Text := CurrToStr(FPriceSys.GetPrice(Price, I));
finally
FSeasonStrategy.Free;
FVIPStrategy.Free;
FTeamStrategy.Free;
FPriceSys.Free;
end;
end;
(*$WARNINGS ON*)
procedure TClient.btnExitClick(Sender: TObject);
begin
Close;
end;
end.