Mode stratégie de programmation en mode Delphi (suite)
Liu Yi
1.3 Application du modèle stratégique dans le système de gestion hôtelière
Dans les systèmes de gestion hôtelière, le prix d’une chambre n’est généralement pas statique. Il devrait y avoir des stratégies de vente différentes pour les hébergements hors-saison et haute saison, pour les anciens clients et les nouveaux clients, pour les clients individuels et les groupes. Bien évidemment, la stratégie commerciale détermine l’offre. Cependant, le système de devis basé sur la stratégie de vente ne peut pas être lié à un client spécifique, car ce n'est qu'en rendant le système de devis basé sur la stratégie de vente indépendant que sa réutilisation et sa maintenabilité peuvent être garanties. Par exemple : d'une part, un système de devis répond aux besoins de plusieurs clients tels que la demande de tarifs préférentiels et le règlement des chambres, d'autre part, il répond aux besoins d'ajustement constant de nouvelles stratégies de vente, ce qui peut réellement permettre une réutilisation et une maintenabilité. . Pour les exigences de conception ci-dessus, il est préférable de choisir le mode stratégie. Le modèle de stratégie permet des changements d'algorithme indépendamment du client qui l'utilise. L'exemple de programme est un module d'interrogation de prix de logement préférentiel basé sur le modèle de stratégie, qui comprend un système de cotation basé sur une stratégie de vente et une interface d'interrogation de prix de logement préférentiel. Bien entendu, l'interface de demande de prix préférentiels n'est qu'un des clients du système de cotation, et le système de cotation peut également être utilisé par d'autres clients. La conception du module de demande de prix préférentiels est illustrée à la figure 1‑6. Il comprend : · La classe de stratégie de vente TSaleStrategy, qui est une classe de base abstraite pour des classes de stratégie de vente spécifiques. · 3 catégories spécifiques de stratégie commerciale : TVipStrategy (stratégie de vente de cartes VIP), TTeamStrategy (stratégie de vente d'équipe), TSeasonStrategy (stratégie de vente saisonnière). · Classe de citation TPRiceContext, qui constitue le contexte de ce modèle de stratégie et contient une référence à TStrategy. · La classe client TClient est une classe de formulaire, qui est l'interface pour la demande de prix de l'immobilier. Figure 1‑6 L'exemple de programme 1‑1 pour le module de demande de tarif de chambre préférentiel basé sur le modèle de stratégie est le code source de l'unité HotelSaleStrategy. Cette unité contient la logique métier du système de devis basé sur la stratégie de vente et est implémentée à l'aide du modèle de stratégie. . En tant que classe de base abstraite de la stratégie de vente, TSaleStrategy vise à fournir une interface commune. La fonction abstraite virtuelle SalePrice est une telle interface. Étant donné que les trois stratégies de vente spécifiques sont formulées en fonction de la saison, de la carte VIP et de la taille de l'équipe, la conception des paramètres de l'interface de classe de base SalePrice doit répondre aux différents besoins des trois classes dérivées. La fonction SalePrice de TSaleStrategy est déclarée comme suit : function SalePrice(price:Currency;value:integer):Currency virtual abstract; Son premier paramètre représente le prix fixe entrant et le deuxième paramètre représente les conditions préférentielles entrantes. pour différentes classes dérivées. Dans la stratégie de vente saisonnière TSeasonStrategy, ce paramètre est exprimé en mois d'enregistrement ; dans la stratégie de vente de cartes VIP TVIPStrategy, ce paramètre est exprimé en type de carte VIP ; dans la stratégie de vente d'équipe TTeamStrategy ; nombre de personnes dans l'équipe. Nous avons constaté que ces paramètres peuvent tous utiliser des types entiers. Ainsi, dans la classe de base, un paramètre de valeur est intelligemment utilisé pour résoudre les différentes exigences de paramètres de la classe dérivée. De cette manière, TPriceContext peut directement mettre les données dans des paramètres et les transmettre à différentes opérations de stratégie de vente, évitant ainsi la redondance des paramètres. {TPriceContext }function TPriceContext.GetPrice(price:Currency;value:integer):Currency;begin result:=Strategy.SalePrice(price,value);end;TPriceContext joue un rôle contextuel dans ce mode stratégique et se charge de référencer les ventes stratégie Différentes instances de l'objet appellent l'interface SalePrice pour configurer dynamiquement l'algorithme de remise spécifique et renvoyer le prix de vente réel. Grâce à l'intermédiaire de TPriceContext, le client n'a pas besoin de savoir comment la stratégie de vente spécifique est mise en œuvre ; de même, lorsque la stratégie de vente est mise à jour et ajustée, cela n'aura aucun impact sur le programme client ; Exemple de programme 1‑1 Code source de l'unité HotelSaleStrategy HotelSaleStrategy ; interface utilise SysUtils, Windows, messages, classes, graphiques, contrôles, formulaires, boîtes de dialogue ; tapez TSaleStrategy = classe (TObject) fonction publique SalePrice (prix : devise ; valeur : entier) : devise ; virtuel ; résumé ; fin ; TSeasonStrategy = fonction publique de classe (TSaleStrategy). SalePrice(price:Currency;value:integer):Currency; end; TVIPStrategy = classe (TSaleStrategy) fonction publique SalePrice(price:Currency;value:integer):Currency end; SalePrice(price:Currency;value:integer):Currency override; (TObject) FStrategy privé : TSaleStrategy ; procédure SetStrategy (Valeur : TSaleStrategy); fonction publique GetPrice (prix : Currency ; valeur : entier): Currency propriété Stratégie : TSaleStrategy lire FStrategy écrire SetStrategy ; TSeasonStrategy.SalePrice(price:Currency;value:integer):Currency;begin //Stratégie de vente saisonnière {15 % de réduction en février, mars et novembre, 10 % de réduction en avril et juin. 8. 9,5 % de réduction en septembre. } valeur de cas de 2,3,11:result:=price*0.85; 4,6:result:=price*0.9; 8,9:result:=price*0.95; TVIPStrategy }function TVIPStrategy.SalePrice(price:Currency;value:integer):Currency;begin //Stratégie de vente de cartes VIP{ 0 : Carte VIP Argent à 10 % de réduction 1 : Carte VIP Gold à 20 % de réduction 2 : Carte VIP Diamond à 30 % de réduction} valeur de cas de 0 : résultat : = prix * 0,9 ; =prix*0,7; fin;fin;{TTeamStrategy }fonction TTeamStrategy.SalePrice(price:Currency;value:integer):Currency;begin //Stratégie de vente d'équipe {10 % de réduction pour une équipe de 3 à 5 personnes ; 20 % de réduction pour une équipe de 6 à 10 personnes ; une équipe de 11 à 20 personnes ; 20 à 40 % de réduction pour les groupes de plus d'une personne. } résultat :=prix ; si (valeur<6) et (valeur>2) alors résultat :=prix*0,9 ; si (valeur<11) et (valeur>5) alors résultat :=prix*0,8 ; 21) et (valeur>10) alors result:=price*0.7; if (value>20) then result:=price*0.6;end;{TPriceContext }function TPriceContext.GetPrice(price:Currency;value:integer):Devise;begin result:=Strategy.SalePrice(price,value);end;procedure TPriceContext.SetStrategy(Value: TSaleStrategy);begin FStrategy:=Value;end;end. Le programme client du module de requête de tarif de chambre préférentiel est présenté dans l'exemple de programme 1-2. Le programme fournit une interface de sélection utilisateur afin que le demandeur puisse choisir un plan préférentiel. Une fois les conditions préférentielles et les tarifs publics sélectionnés, cliquez sur le bouton « Vérifier les tarifs préférentiels » pour bénéficier des tarifs réduits. L'effet opérationnel réel est illustré à la figure 1-7. Exemple de programme 1‑2 Unité de code source de l'unité ClientForm ; interface utilise Windows, Messages, SysUtils, Variantes, Classes, Graphiques, Contrôles, Formulaires, Boîtes de dialogue, StdCtrls, ExtCtrls, HotelSaleStrategy, ComCtrls, DateUtils, type TClient = class(TForm) RadioGroup1 : TRadioGroup ; btnCheck : TButton ; btnExit : TButton ; dtpDate : TDateTimePicker ; cmbVIP : TComboBox ; Étiquette 1 : TLabel ; cmbPrice : TComboBox ; Étiquette3 : TLabel ; procédure FormCreate(Expéditeur : TObject); procédure btnCheckClick(Expéditeur: TObject); procédure FormDestroy(Expéditeur: TObject); procédure btnExitClick(Expéditeur: TObject); procédure privée FSeasonStrategy:TSaleStrategy; TPrixContext ; public { Déclarations publiques } 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 ; .DateHeure); fin ; 1 : début FPriceSys.Strategy:=FVIPStrategy ; i:=cmbVIP.ItemIndex ; fin ; 2 : début FPriceSys.Strategy :=FTeamStrategy ; i:=StrToInt(edtCount.Text); fin ; 300 ; //La chambre standard de classe A coûte 300 yuans 1 :prix :=500 ; //Chambre standard de classe B 500 yuans 2:prix:=800; //Chambre VIP 800 yuans 3:prix:=1000 //Suite affaires 1000 yuans 4:prix:=2000 //Suite de luxe 2000 yuansend; Text:=CurrToStr(FPriceSys.GetPrice(price,i));fin;procédure TClient.FormDestroy(Expéditeur : TObject); commencer FPriceSys.Free; FSeasonStrategy.Free; FVIPStrategy.Free; fin; procédure TClient.btnExitClick (Expéditeur : TObject); edtCount.Enabled:=false; cmbVIP.Enabled:=false; cas RadioGroup1.ItemIndex de 0:dtpDate.Enabled:=true; 1:cmbVIP.Enabled:=true; fin Figure 1-7 L'interface d'exécution réelle du module de requête de prix préférentiel.
1.4 Résumé de la pratique
Grâce à la démonstration et à l'analyse des exemples précédents, nous discutons plus en détail du modèle de stratégie comme suit : · Le modèle de stratégie fournit un moyen de gérer un ensemble d'algorithmes. La hiérarchie des classes de stratégie définit une série d'algorithmes ou de comportements réutilisables pour TContext. La classe de base TStrategy extrait les fonctions communes de ces algorithmes, et les classes dérivées enrichissent les différences et les types d'algorithmes par héritage et évitent la duplication de code. · Si vous ne séparez pas l'algorithme du contexte dans lequel l'algorithme est utilisé, et que vous générez directement une classe dérivée de la classe TContext qui contient l'algorithme, et que vous lui donnez des comportements différents, cela codera en dur le comportement dans TContext, et séparer l'implémentation de l'algorithme de TContext. Les implémentations sont mélangées, ce qui rend TContext difficile à comprendre, à maintenir et à étendre. Le résultat final est un ensemble de classes liées, la seule différence entre elles est l'algorithme qu'elles utilisent. Évidemment, la relation d'héritage des classes est une association forte, et la relation d'héritage ne peut pas modifier dynamiquement l'algorithme ; tandis que la relation de composition des objets est une association faible, en combinant des objets de classe stratégique, l'algorithme peut évoluer indépendamment de l'environnement (TContext). dans lequel l'algorithme est utilisé. · Utilisez le modèle de stratégie pour refactoriser les codes de programme qui utilisent un grand nombre d'instructions de branchement conditionnelles. Lorsque différents comportements sont empilés dans une classe, il est difficile d’éviter d’utiliser des instructions conditionnelles pour sélectionner le comportement approprié. L'encapsulation du comportement dans des classes de stratégie distinctes élimine ces instructions conditionnelles. · Un trop grand nombre d'algorithmes peut entraîner un grand nombre d'objets politiques. Afin de réduire la surcharge du système, l'état qui dépend de l'environnement de l'algorithme peut généralement être enregistré sur le client, et TStrategy est implémenté en tant qu'objet sans état pouvant être partagé par différents clients. Tout état externe est maintenu par TContext. TContext transmet cet état à chaque requête à l'objet TStrategy. Par exemple, dans l'exemple de programme, j'enregistre le mois d'enregistrement du statut externe de TSeasonStrategy, le type de carte VIP de statut externe de TVIPStrategy et la taille de l'équipe de statut externe de TTeamStrategy sur le client, et je transmets ces statuts à la classe de stratégie de vente via TPriceContext. L'avantage est que la classe de stratégie de vente devient apatride et peut être partagée par d'autres modules tels que le module de règlement des salles. · Que l'algorithme implémenté par chaque stratégie spécifique soit simple ou complexe, ils partagent tous l'interface définie par TStrategy. Il est donc probable que certaines politiques spécifiques n'utiliseront pas toutes les informations qui leur sont transmises via cette interface. Si je conçois l'interface de TSaleStrategy comme ceci dans l'exemple de programme :
SalePrice(prix:Devise;Mois:entier;VIP:entier;
Nombre : entier : Devise ;
Certains de ces paramètres ne seront jamais utilisés par certaines classes de stratégie commerciale. Cela signifie que parfois TContext créera et initialisera des paramètres qui ne seront jamais utilisés. Si un tel problème existe et que vous ne pouvez pas utiliser les techniques de l'exemple de programme, vous pouvez uniquement adopter une méthode étroitement couplée entre TStrategy et TContext.
D'autres articles connexes et des exemples de codes sources de programmes peuvent être téléchargés à partir du site Web de l'auteur : http://www.liu-yi.net