Strategiemodus der Delphi-Modus-Programmierung (Fortsetzung)
Liu Yi
1.3 Anwendung des Strategiemodells im Hotelmanagementsystem
In Hotelmanagementsystemen ist der Preis eines Zimmers normalerweise nicht statisch. Für die Neben- und Hauptsaison von Unterkünften, Altkunden und Neukunden, Einzelgästen und Gruppen sollte es unterschiedliche Verkaufsstrategien geben. Offensichtlich bestimmt die Verkaufsstrategie das Angebot. Allerdings kann das auf der Vertriebsstrategie basierende Angebotssystem nicht an einen bestimmten Kunden gebunden werden, da nur durch die Unabhängigkeit des auf der Vertriebsstrategie basierenden Angebotssystems dessen Wiederverwendbarkeit und Wartbarkeit gewährleistet werden kann. Ein Beispiel: Ein Angebotssystem erfüllt einerseits die Bedürfnisse mehrerer Kunden, z. B. die Anfrage nach Vorzugszimmerpreisen und die Zimmerabrechnung, andererseits erfüllt es die Bedürfnisse einer ständigen Anpassung neuer Verkaufsstrategien. Dadurch kann tatsächlich Wiederverwendbarkeit und Wartbarkeit erreicht werden . . Für die oben genannten Designanforderungen ist es am besten, den Strategiemodus zu wählen. Das Strategiemuster ermöglicht Algorithmusänderungen unabhängig vom Client, der es verwendet. Das Beispielprogramm ist ein Modul zur Abfrage von Vorzugspreisen für Immobilien, das auf dem Strategiemodell basiert und ein Angebotssystem basierend auf der Verkaufsstrategie und eine Schnittstelle zur Abfrage von Vorzugspreisen für Wohnimmobilien umfasst. Natürlich ist die Schnittstelle zur Vorzugspreisanfrage nur einer der Clients des Angebotssystems, und das Angebotssystem kann auch von anderen Clients genutzt werden. Der Aufbau des Vorzugspreis-Anfragemoduls ist in Abbildung 1-6 dargestellt. Es umfasst: · Die Vertriebsstrategieklasse TSaleStrategy, eine abstrakte Basisklasse für bestimmte Vertriebsstrategieklassen. · 3 spezifische Verkaufsstrategiekategorien: TVipStrategy (VIP-Karten-Verkaufsstrategie), TTeamStrategy (Team-Verkaufsstrategie), TSeasonStrategy (saisonale Verkaufsstrategie). · Zitatklasse TPRiceContext, die den Kontext in diesem Strategiemuster darstellt und einen Verweis auf TStrategy enthält. · Die Client-Klasse TClient ist eine Formularklasse, die die Schnittstelle für die Immobilienpreisabfrage darstellt. Abbildung 1-6 Beispielprogramm 1-1 für das Anfragemodul für Vorzugszimmerpreise basierend auf dem Strategiemuster ist der Quellcode der HotelSaleStrategy-Einheit. Diese Einheit enthält die Geschäftslogik des Angebotssystems basierend auf der Verkaufsstrategie und wird mithilfe des Strategiemusters implementiert . Als abstrakte Basisklasse der Vertriebsstrategie zielt TSaleStrategy darauf ab, eine gemeinsame Schnittstelle bereitzustellen. Die virtuelle abstrakte Funktion SalePrice ist eine solche Schnittstelle. Da die drei spezifischen Verkaufsstrategien auf der Grundlage von Saison, VIP-Karte und Teamgröße formuliert werden, muss das Parameterdesign der Basisklassenschnittstelle SalePrice den unterschiedlichen Anforderungen der drei abgeleiteten Klassen gerecht werden. Die SalePrice-Funktion von TSaleStrategy wird wie folgt deklariert: function SalePrice(price:Currency;value:integer):Currency; Der erste Parameter repräsentiert den eingehenden Festpreis und der zweite Parameter stellt die eingehenden Vorzugskonditionen dar für verschiedene abgeleitete Klassen. In der saisonalen Verkaufsstrategie TSeasonStrategy wird dieser Parameter als Check-in-Monat ausgedrückt; in der VIP-Karten-Verkaufsstrategie TVIPStrategy wird dieser Parameter als Typ der VIP-Karte ausgedrückt Anzahl der Personen im Team. Wir haben festgestellt, dass diese Parameter alle ganzzahlige Typen verwenden können. Daher wird in der Basisklasse ein Wertparameter geschickt verwendet, um die unterschiedlichen Parameteranforderungen der abgeleiteten Klasse zu lösen. Auf diese Weise kann TPriceContext Daten direkt in Parameter einfügen und an verschiedene Vertriebsstrategieoperationen übergeben, wodurch Parameterredundanz vermieden wird. {TPriceContext }function TPriceContext.GetPrice(price:Currency;value:integer):Currency;begin result:=Strategy.SalePrice(price,value);end;TPriceContext spielt in diesem Strategiemodus eine kontextbezogene Rolle und ist für die Referenzierung der Verkäufe verantwortlich Strategie Verschiedene Instanzen des Objekts rufen die SalePrice-Schnittstelle auf, um den spezifischen Rabattalgorithmus dynamisch zu konfigurieren und den tatsächlichen Verkaufspreis zurückzugeben. Aufgrund der Vermittlung von TPriceContext muss der Kunde nicht wissen, wie die spezifische Vertriebsstrategie umgesetzt wird. Auch wenn die Vertriebsstrategie aktualisiert und angepasst wird, hat dies keine Auswirkungen auf das Kundenprogramm. Beispielprogramm 1-1 Quellcode der HotelSaleStrategy-Einheit HotelSaleStrategy;interfaceuses SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs;type TSaleStrategy = class (TObject) public function SalePrice(price:Currency;value:integer): Währung ; virtual; abstract; TSeasonStrategy = öffentliche Funktion der Klasse (TSaleStrategy). SalePrice(price:Currency;value:integer):Currency; override; end; TVIPStrategy = class (TSaleStrategy) public function SalePrice(price:Currency;value:integer):Currency; TPriceContext = class (TObject) private FStrategy: TSaleStrategy; procedure SetStrategy(Value: TSaleStrategy); public function GetPrice(price:Currency;value:integer):Currency; property Strategy: TSaleStrategy read SetStrategy; end;implementation{TSeasonStrategy}function TSeasonStrategy.SalePrice(price:Currency;value:integer):Currency;begin //Saisonale Verkaufsstrategie {15 % Rabatt im Februar, März und November, 10 % Rabatt im April und Juni. 8. 9,5 % Rabatt im September. } case value of 2,3,11:result:=price*0.95; 4,6:result:=price*0.95; else result:=price*0.95; TVIPStrategy }function TVIPStrategy.SalePrice(price:Currency;value:integer):Currency;begin //VIP-Karten-Verkaufsstrategie{ 0:VIP Silver Card 10 % Rabatt 1:VIP Gold Card 20 % Rabatt 2:VIP Diamond Card 30 % Rabatt} Fallwert von 0:Ergebnis:=Preis*0,9; 1:Ergebnis:=Preis*0,8; =price*0.7; end;end;{TTeamStrategy }Funktion TTeamStrategy.SalePrice(price:Currency;value:integer):Currency;begin //Team-Verkaufsstrategie {10 % Rabatt für ein Team von 3–5 Personen; 20 % Rabatt für ein Team von 6–10 Personen; ein Team von 11-20 Personen; 20 40 % Rabatt für Gruppen von mehr als 1 Person. } Ergebnis:=Preis; wenn (Wert<6) und (Wert>2), dann Ergebnis:=Preis*0,9; wenn (Wert<11) und (Wert>5), dann Ergebnis:=Preis*0,8; 21) und (Wert>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. Das Client-Programm des Abfragemoduls für Vorzugszimmerpreise ist in Beispielprogramm 1-2 dargestellt. Das Programm bietet eine Benutzerauswahlschnittstelle, sodass der Anfragende einen bevorzugten Plan auswählen kann. Sobald Sie die Vorzugskonditionen und öffentlichen Tarife ausgewählt haben, klicken Sie auf die Schaltfläche „Vorzugspreise prüfen“, um die ermäßigten Tarife zu erhalten. Der tatsächliche Betriebseffekt ist in Abbildung 1-7 dargestellt. Beispielprogramm 1-2 ClientForm-Unit-Quellcode-Einheit ClientForm; Schnittstelle verwendet Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, HotelSaleStrategy, ComCtrls,DateUtils; type TClient = class(TForm) RadioGroup1 : TRadioGroup; btnCheck: TButton; btnExit: TDateTimePicker; cmbVIP: TLabel; edtPrice: TEdit; Label5: TLabel; Prozedur FormCreate(Sender: TObject); procedure btnCheckClick(Sender: TObject); procedure RadioGroup1Click(Sender: TObject); FTeamStrategy:TSaleStrategy; TPriceContext; öffentlich { Öffentliche Deklarationen } end;var Client: TClient;implementation{$R *.dfm}procedure TClient.FormCreate(Sender: TObject);begin FSeasonStrategy:=TSeasonStrategy.Create; FVIPStrategy:=TVIPStrategy.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 ; i:=cmbVIP.ItemIndex; end 2:begin FPriceSys.Strategy ; i:=StrToInt(edtCount.Text); end; 300; //Standardzimmer der Klasse A kostet 300 Yuan 1:Preis:=500; //Standardzimmer der Klasse B 500 Yuan 2:Preis:=800; //Business Suite 1000 Yuan 4:Preis:=2000; // Deluxe Suite 2000 Yuanend; Text:=CurrToStr(FPriceSys.GetPrice(price,i));end;procedure TClient.FormDestroy(Sender: TObject); begin FPriceSys.Free; FVIPStrategy.Free;end; edtCount.Enabled:=false; cmbVIP.Enabled:=false; case RadioGroup1.ItemIndex of 0:dtpDate.Enabled:=true; Abbildung 1-7 Die tatsächliche laufende Schnittstelle des Vorzugspreis-Abfragemoduls
1.4 Zusammenfassung der Praxis
Durch die Demonstration und Analyse der vorherigen Beispiele diskutieren wir das Strategiemuster weiter wie folgt: · Das Strategiemuster bietet eine Möglichkeit, eine Reihe von Algorithmen zu verwalten. Die Hierarchie der Strategieklassen definiert eine Reihe wiederverwendbarer Algorithmen oder Verhaltensweisen für TContext. Die TStrategy-Basisklasse extrahiert die gemeinsamen Funktionen in diesen Algorithmen, und die abgeleiteten Klassen bereichern die Unterschiede und Typen der Algorithmen durch Vererbung und vermeiden die Duplizierung von Code. · Wenn Sie den Algorithmus nicht vom Kontext trennen, in dem der Algorithmus verwendet wird, und direkt eine abgeleitete Klasse der TContext-Klasse generieren, die den Algorithmus enthält, und ihr unterschiedliche Verhaltensweisen zuweisen, wird dies das Verhalten in TContext fest codieren und Trennen Sie die Implementierung des Algorithmus von TContext. Die Implementierungen sind gemischt, was es schwierig macht, TContext zu verstehen, zu warten und zu erweitern. Das Endergebnis ist eine Reihe verwandter Klassen. Der einzige Unterschied zwischen ihnen ist der von ihnen verwendete Algorithmus. Offensichtlich ist die Vererbungsbeziehung von Klassen eine starke Assoziation, und die Vererbungsbeziehung kann den Algorithmus nicht dynamisch ändern, während die Zusammensetzungsbeziehung von Objekten eine schwache Assoziation ist. Durch die Kombination von Strategieklassenobjekten kann sich der Algorithmus unabhängig von der Umgebung (TContext) entwickeln. in dem der Algorithmus verwendet wird. · Verwenden Sie das Strategiemuster, um Programmcodes umzugestalten, die eine große Anzahl bedingter Verzweigungsanweisungen verwenden. Wenn unterschiedliche Verhaltensweisen in einer Klasse gestapelt werden, ist es schwierig, die Verwendung von bedingten Anweisungen zur Auswahl des geeigneten Verhaltens zu vermeiden. Durch die Kapselung des Verhaltens in separaten Richtlinienklassen entfallen diese bedingten Anweisungen. · Zu viele Algorithmen können zu einer großen Anzahl von Richtlinienobjekten führen. Um den Systemaufwand zu reduzieren, kann der von der Algorithmusumgebung abhängige Status normalerweise auf dem Client gespeichert werden, und TStrategy wird als zustandsloses Objekt implementiert, das von verschiedenen Clients gemeinsam genutzt werden kann. Jeder externe Status wird von TContext verwaltet. TContext übergibt diesen Status bei jeder Anfrage an das TStrategy-Objekt. Im Beispielprogramm speichere ich beispielsweise den Check-in-Monat des externen Status von TSeasonStrategy, den VIP-Kartentyp des externen Status von TVIPStrategy und die Teamgröße des externen Status von TTeamStrategy auf dem Client und übergebe diese Status über TPriceContext an die Vertriebsstrategieklasse. Dies hat den Vorteil, dass die Vertriebsstrategieklasse zustandslos wird und von anderen Modulen wie dem Raumabrechnungsmodul gemeinsam genutzt werden kann. · Unabhängig davon, ob der von jeder spezifischen Strategie implementierte Algorithmus einfach oder komplex ist, teilen sie alle die von TStrategy definierte Schnittstelle. Daher ist es wahrscheinlich, dass einige spezifische Richtlinien nicht alle Informationen nutzen, die ihnen über diese Schnittstelle übermittelt werden. Wenn ich die Schnittstelle von TSaleStrategy im Beispielprogramm so gestalte:
SalePrice(price:Currency;Monat:integer;VIP:integer;
Anzahl:Ganzzahl):Währung;
Einige dieser Parameter werden von bestimmten Vertriebsstrategieklassen niemals verwendet. Das bedeutet, dass TContext manchmal Parameter erstellt und initialisiert, die nie verwendet werden. Wenn ein solches Problem auftritt und Sie die Techniken im Beispielprogramm nicht verwenden können, können Sie nur eine eng gekoppelte Methode zwischen TStrategy und TContext anwenden.
Weitere verwandte Artikel und Beispielprogramm-Quellcodes können von der Website des Autors heruntergeladen werden: http://www.liu-yi.net