麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > Delphi > 正文

Delphi模式編程之策略模式(下)

2019-11-18 18:23:03
字體:
來源:轉載
供稿:網友

Delphi模式編程之策略模式(續)

劉 藝

1.3                         策略模式在酒店管理系統中的應用

在酒店管理系統中,通常客房的價格不是一成不變的。對于住宿的淡季和旺季、老客戶和新客戶、散客和團隊,都應該有不同的銷售策略。顯然,銷售策略決定了報價。但是基于銷售策略的報價體系又不能綁定于某一具體的客戶端,因為只有把基于銷售策略的報價體系獨立出來,才能保證其重用性和可維護性。比如:一種報價體系一方面滿足了優惠房價查詢、客房結算等多個客戶端的使用,另一方面又滿足了不斷調整的新銷售策略的需求,這才算真正做到了重用性和可維護性。
對于以上的設計要求,選用策略模式是最好不過了。策略模式能夠讓算法變化獨立于使用它的客戶端。范例程序是一個基于策略模式的優惠房價查詢模塊,它包括一個基于銷售策略的報價體系和一個優惠房價查詢界面。當然,優惠房價查詢界面只是該報價體系的客戶端之一,報價體系亦可被其他客戶端使用。
優惠房價查詢模塊的設計如圖 1‑6所示。它包括了:
·           銷售策略類TSaleStrategy,它是具體銷售策略類的抽象基類。
·           3個具體銷售策略類:TVipStrategy (VIP卡銷售策略)、TTeamStrategy (團隊銷售策略)、TSeasonStrategy(季節銷售策略)。
·           報價類TPRiceContext,它是該策略模式中的上下文,持有一個到TStrategy的引用。
·           客戶端類TClient,它是一個窗體類,即房價查詢的界面。
 
1‑6 基于策略模式的優惠房價查詢模塊
示例程序 1‑1是HotelSaleStrategy單元的源代碼,該單元包含了基于銷售策略的報價體系的業務邏輯,用策略模式實現。TSaleStrategy作為銷售策略的抽象基類,其目的是提供一個通用的接口。虛抽象函數SalePrice就是這樣一個接口。由于3個具體銷售策略分別是根據季節、VIP卡、團隊人數來制定銷售策略的,所以基類接口SalePrice的參數設計必須滿足3個派生類的不同需求。TSaleStrategy的SalePrice函數聲明如下:
 
function SalePrice(price:Currency;value:integer):Currency;
virtual; abstract;
 
 
它的第一個參數表示傳入的固定房價,第二個參數表示傳入的優惠條件,該條件因不同的派生類而異。在季節銷售策略TSeasonStrategy中,該參數表示為入住月份;在VIP卡銷售策略TVIPStrategy中,該參數表示為VIP卡的種類;在團隊銷售策略TTeamStrategy中,該參數表示為團隊人數。我們發現,這些參數都可以用整數類型,所以在基類中,巧妙地用一個value參數解決了派生類的不同參數需求。這樣一來,可以直接讓TPriceContext將數據放在參數中傳遞給不同的銷售策略類操作,避免了參數冗余。
 
{TPriceContext }
function TPriceContext.GetPrice(price:Currency;value:integer):Currency;
begin
  result:=Strategy.SalePrice(price,value);
end;
 
TPriceContext在該策略模式中起著上下文作用,它負責引用銷售策略對象的不同實例,調用SalePrice接口,動態配置具體的折扣算法,并返回實際銷售價格。由于有了TPriceContext的中介,客戶端無需知道具體銷售策略是如何實現的;同樣,當銷售策略進行更新調整時,對客戶端程序亦無影響。
示例程序 1‑1 HotelSaleStrategy單元的源代碼
unit HotelSaleStrategy;
 
interface
 
uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,
  Forms, Dialogs;
 
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*0.9;
    1:result:=price*0.8;
    2:result:=price*0.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;
  if (value<11) and (value>5) then  result:=price*0.8;
  if (value<21) and (value>10) then  result:=price*0.7;
  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.
 
優惠房價查詢模塊的客戶端程序如示例程序 1‑2所示。該程序提供一個用戶選擇界面,使得查詢者可以任選一種優惠方案。一旦選定優惠條件和公開房價,點擊“查詢優惠房價”按鈕,便得到打折后的優惠價。實際運行效果如圖 1‑7所示。
示例程序 1‑2 ClientForm單元的源代碼
unit ClientForm;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls,HotelSaleStrategy, ComCtrls,DateUtils;
 
type
  TClient = class(TForm)
    RadioGroup1: TRadioGroup;
    btnCheck: TButton;
    btnExit: TButton;
    dtpDate: TDateTimePicker;
    cmbVIP: TComboBox;
    Label1: TLabel;
    Label2: TLabel;
    cmbPrice: TComboBox;
    edtPrice: TEdit;
    Label3: TLabel;
    edtCount: TEdit;
    Label4: TLabel;
    Label5: TLabel;
    Bevel1: TBevel;
    procedure FormCreate(Sender: TObject);
    procedure btnCheckClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnExitClick(Sender: TObject);
    procedure RadioGroup1Click(Sender: TObject);
  private
    FSeasonStrategy:TSaleStrategy;
    FVIPStrategy:TSaleStrategy;
    FTeamStrategy:TSaleStrategy;
    FPriceSys:TPriceContext;
  public
    { Public declarations }
  end;
 
var
  Client: TClient;
 
implementation
 
 
{$R *.dfm}
 
procedure TClient.FormCreate(Sender: TObject);
begin
  FSeasonStrategy:=TSeasonStrategy.Create;
  FVIPStrategy:=TVIPStrategy.Create;
  FTeamStrategy:=TTeamStrategy.Create;
  FPriceSys:=TPriceContext.Create;
end;
 
procedure TClient.btnCheckClick(Sender: TObject);
var
  i:integer;
  price:Currency;
begin
  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));
end;
 
procedure TClient.FormDestroy(Sender: TObject);
begin
  FPriceSys.Free;
  FSeasonStrategy.Free;
  FVIPStrategy.Free;
  FTeamStrategy.Free;
end;
 
procedure TClient.btnExitClick(Sender: TObject);
begin
  close;
end;
 
procedure TClient.RadioGroup1Click(Sender: TObject);
begin
  dtpDate.Enabled:=false;
  edtCount.Enabled:=false;
  cmbVIP.Enabled:=false;
  case RadioGroup1.ItemIndex of
    0:dtpDate.Enabled:=true;
    1:cmbVIP.Enabled:=true;
    2:edtCount.Enabled:=true;
  end;
end;
 
end.
1‑7優惠房價查詢模塊的實際運行界面

1.4                         實踐小結

通過前面范例的演示和剖析,我們進一步討論策略模式如下:
·           策略模式提供了管理算法集的辦法。策略類的層次結構為TContext定義了一系列的可供重用的算法或行為。TStrategy基類析取出這些算法中的公共功能,派生類通過繼承豐富了算法的差異和種類,又避免了重復的代碼。
·           如果不將算法和使用算法的上下文分開,直接生成一個包含算法的TContext類的派生類,給它以不同的行為,這將會把行為寫死到TContext中,而將算法的實現與TContext的實現混合起來,從而使TContext難以理解、難以維護和難以擴展。最后得到一大堆相關的類, 它們之間的唯一差別是它們所使用的算法。顯然,類的繼承關系是強關聯,繼承關系無法動態地改變算法;而對象的合成關系是弱關聯,通過組合策略類對象,使得算法可以獨立于使用算法的環境(TContext)而獨立演化。
·           使用策略模式可以對大量使用條件分支語句的程序代碼進行重構。當不同的行為堆砌在一個類中時,很難避免使用條件語句來選擇合適的行為。將行為封裝在一個個獨立的策略類中消除了這些條件語句。
·           過多的算法可能會導致策略對象的數目很大。為了減少系統開銷,通常可以把依賴于算法環境的狀態保存在客戶端,而將TStrategy實現為可供各客戶端共享的無狀態的對象。任何外部的狀態都由TContext維護。TContext在每一次對TStrategy對象的請求中都將這個狀態傳遞過去。比如范例程序中,我將TSeasonStrategy的外部狀態入住月份、TVIPStrategy的外部狀態VIP卡的種類、TTeamStrategy的外部狀態團隊人數都保存在客戶端,并通過TPriceContext將這些狀態傳遞給銷售策略類。這樣做的好處是銷售策略類變成無狀態的了,它們同時可以被客房結算模塊等其他模塊共享。
·           無論各個具體策略實現的算法是簡單還是復雜, 它們都共享TStrategy定義的接口。因此很可能某些具體策略不會都用到所有通過這個接口傳遞給它們的信息。如果我在范例程序中把TSaleStrategy的接口設計成這樣:
SalePrice(price:Currency;Month:integer;VIP:integer;
                                                 Count:integer):Currency;

其中的一些參數永遠不會被某些具體銷售策略類用到。這就意味著有時TContext會創建和初始化一些永遠不會用到的參數。如果存在這樣問題,又無法使用范例程序中的技巧,那么只能在TStrategy和TContext之間采取緊耦合的方法。


更多相關文章和示例程序源代碼可以到作者網站下載:http://www.liu-yi.net


上一篇:在Delphi中如何維護COM+的狀態信息

下一篇:Delphi7目錄結構----初學者參考

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

主站蜘蛛池模板: 久久精品国产清自在天天线 | 一级成人免费 | 欧美成年人视频在线观看 | 91久久91久久精品免观看 | 亚洲精品欧美二区三区中文字幕 | 天天天干夜夜夜操 | a一级黄色毛片 | 噜噜噜躁狠狠躁狠狠精品视频 | 91九色蝌蚪在线 | 精品91av | 嗯~啊~弄嗯~啊h高潮视频 | 香蕉久久久| 久久久麻豆| 日韩精品中文字幕一区二区三区 | 视频一区二区视频 | 99爱福利视频在线观看 | 亚洲成人在线视频网 | 精品国产乱码久久久久久丨区2区 | 欧美三级日本三级少妇99 | 国产无遮挡一级毛片 | 久久精品日本一区 | 午夜小视频免费观看 | 成人三级电影网站 | 二区三区在线观看 | 国色天香综合网 | 国产又粗又爽又深的免费视频 | 一级毛片电影网 | 99精品视频在线观看免费播放 | 久久久免费| 91aa.app| 香蕉视频h| 国产999精品久久久久 | 欧美日韩免费一区 | 日韩av在线播放一区 | 天天看天天摸天天操 | 免费国产自久久久久三四区久久 | 国产又白又嫩又紧又爽18p | 成人在线视频在线观看 | xnxx 美女19| 午夜生活理论片 | 久久久久中精品中文字幕19 |