Stratégie (patron de conception)

En génie logiciel, le patron stratégie est un patron de conception (design pattern) de type comportemental grâce auquel des algorithmes peuvent être sélectionnés à la volée au cours du temps d'exécution selon certaines conditions.

Le patron de conception stratégie est utile pour des situations où il est nécessaire de permuter dynamiquement les algorithmes utilisés dans une application. Le patron stratégie est prévu pour fournir le moyen de définir une famille d'algorithmes, encapsuler chacun d'eux en tant qu'objet, et les rendre interchangeables. Ce patron laisse les algorithmes changer indépendamment des clients qui les emploient.

Utilisation

Dès lors qu'un objet peut effectuer plusieurs traitements différents, dépendant d'une variable ou d'un état[1].

Structure

Patron Stratégie en UML
Patron Stratégie en LePUS3 (legend)

Exemple en C++

#include <iostream>
#include <memory>

// IStrategie est l’interface permettant d’exécuter un algorithme
class IStrategie
{
public:
    void execute() { process(); } // NVI

    virtual ~IStrategie() = default; // Héritage, donc destructeur public virtuel

private:
    virtual void process() = 0; // IStrategie::process() est une fonction virtuelle pure
                                // et de ce fait IStrategie est une classe abstraite
                                // autrement dit une classe qui ne peut être instanciée
};

class AlgorithmeA : public IStrategie
{
private:
    // Chaque Algorithme redéfinit la façon de procéder
    void process() override
    {
        std::cout << "Traitement A" << std::endl;
    }
};

class AlgorithmeB : public IStrategie
{
private:
    void process() override
    {
        std::cout << "Traitement B" << std::endl;
    }
};

class AlgorithmeC : public IStrategie
{
private:
    void process() override
    {
        std::cout << "Traitement C" << std::endl;
    }
};

// Contexte est la classe visible par le client.
// Elle fait le lien entre les demandes du client et l’algorithme (ou les algorithmes) à utiliser.
class Contexte final
{
private:
    std::unique_ptr<IStrategie> strategie;

public:
    Contexte(std::unique_ptr<IStrategie> new_strategie)
        : strategie(std::move(new_strategie))
    {}

    void execute()
    {
        strategie->execute();
    }

    void setAlgorithme(std::unique_ptr<IStrategie> new_strategie)
    {
        strategie = std::move(new_strategie);
    }
};

int main()
{
    Contexte contexte(std::make_unique<AlgorithmeA>());
    contexte.execute();     // Le contexte va effectuer le traitement A

    contexte.setAlgorithme(std::make_unique<AlgorithmeB>());
    contexte.execute();     // Le contexte va effectuer le traitement B

    contexte.setAlgorithme(std::make_unique<AlgorithmeC>());
    contexte.execute();     // Le contexte va effectuer le traitement C

    return 0;
 }

Voir classe abstraite et fonction virtuelle pure.

Exemple en C#

Des idées semblables amènent à une réalisation à l'aide d'interface.

L'objet qui doit avoir une stratégie adaptable à l'exécution implémente IStrategie : la même interface que d'autres objets. L'objet principal délègue l'exécution de la tâche à un autre objet membre qui implémente IStrategie.

L'objet membre étant déclaré dans la classe comme une interface, son implémentation importe peu, on peut donc changer de stratégie à l'exécution. Cette manière de faire se rapproche du Principe de l'injection de dépendance.

using System;

/// <summary> La manière dont le grand général guidera ses troupes</summary>
interface IStrategie {
    void MettreEnOeuvre();
}

/// <summary> Ce grand homme qui fera bientôt des choix décisifs </summary>
class SeigneurDeLaGuerre {

    /// <summary> une stratégie générique </summary>
    IStrategie _strategie;

    /// <summary> comment changer de stratégie </summary>
    public IStrategie Strategie { set { _strategie = value; } }

    /// <summary> délégation de la tâche </summary>
    public void PrendreLaVille() {
        _strategie.MettreEnOeuvre();
    }
}

class DéfoncerLePontLevisDeFace : IStrategie {
    public void MettreEnOeuvre() {
        Console.WriteLine("Prendre la ville de face en défonçant le pont-levis.");
    }
}
class PasserParLaFaceNord : IStrategie {
    public void MettreEnOeuvre() {
        Console.WriteLine("Prendre la ville en escaladant la muraille nord.");
    }
}
class AttendreQueLaVilleSeRende : IStrategie {
    public void MettreEnOeuvre() {
        Console.WriteLine("Attendre qu'il n'y ait plus rien à manger en ville "
            + "et que tout le monde meure de faim.");
    }
}
class SeMarierAvecLaCousineDuDuc : IStrategie {
    public void MettreEnOeuvre() {
        Console.WriteLine("Organiser un mariage avec la cousine du Duc "
            + "alors qu'elle rejoint la ville de retour des Baléares "
            + "et inviter toute la ville à une grande fête.");
    }
}
/// <summary> Différentes situations </summary>
enum Météo {
    IlFaitBeau,
    IlYADuBrouillard,
    IlFaitTropChaudPourTravailler,
    IlPleut
}

class Program {
    static void Main() {

        // notre acteur
        var kevin = new SeigneurDeLaGuerre();

        // les aléas du système
        var météo = (Météo)(new Random().Next(0, 4));

        // une liaison tardive
        switch (météo) {
            case Météo.IlFaitBeau: 
                kevin.Strategie = new DéfoncerLePontLevisDeFace(); break;
            case Météo.IlYADuBrouillard: 
                kevin.Strategie = new PasserParLaFaceNord(); break;
            case Météo.IlFaitTropChaudPourTravailler:
                kevin.Strategie = new AttendreQueLaVilleSeRende(); break;
            case Météo.IlPleut:
                kevin.Strategie = new SeMarierAvecLaCousineDuDuc(); break;
            default: 
                throw new Exception("Nan finalement seigneur de la guerre c'est "
                    + "pas cool comme job : vous décidez d'aller cueillir "
                    + "des champignons dans le Périgord.");
        }

        // une exécution aux petits oignons
        kevin.PrendreLaVille();
    }
}

Exemple en Delphi

Source : Delphi GOF Design Patterns (CodePlex)

unit strategy;

interface

type

 TContext = class;

 IStrategy = interface
 ['{7F63C143-98D0-4B8C-A02B-894D145BB745}']
   function Move(c: TContext): integer;
 end;

 TStrategy1 = class(TInterfacedObject, IStrategy)
 public
   function Move(c: TContext): integer;
 end;

 TStrategy2 = class(TInterfacedObject, IStrategy)
 public
   function Move(c: TContext): integer;
 end;

 TContext = class
 private
   FStrategy: IStrategy;
   FCounter: integer;
 public
   constructor Create(counter: integer);
   function Algorithm: integer;
   procedure SetStrategy(s: IStrategy);
   property counter: integer read FCounter write FCounter;
 end;

implementation

{ TStrategy1 }

function TStrategy1.Move(c: TContext): integer;
begin
 c.Counter := c.Counter + 1;
 Result := c.Counter;
end;

{ TStrategy2 }

function TStrategy2.Move(c: TContext): integer;
begin
 c.Counter := c.Counter - 1;
 Result := c.Counter;
end;

{ TContext }

function TContext.Algorithm: integer;
begin
 Result := FStrategy.Move(Self)
end;

constructor TContext.Create(counter: integer);
begin
 inherited;
 FCounter := counter;
 FStrategy := TStrategy1.Create;
end;

procedure TContext.SetStrategy(s: IStrategy);
begin
 FStrategy := s;
end;

end.


{ fichier projet }
program Behavioral.strategy.Pattern;
{$APPTYPE CONSOLE}

uses
  SysUtils,
  strategy in 'strategy.pas';

var
 context: TContext;
 i: integer;

begin
 try
   context := TContext.Create(12);
   context.SetStrategy(TStrategy1.Create);
   try
     for i := 0 to 30 do begin
       if i =  15 then begin
         WriteLn(#10 + '|| ');
         context.SetStrategy(TStrategy2.Create);
       end;
       Write(IntToStr(context.Algorithm) + ' ');
     end;
     ReadLn;
   finally
     context.Free;
   end;
 except
   on E:Exception do
     Writeln(E.Classname, ': ', E.Message);
 end;
end.

Exemple en Java

Diagramme UML
Diagramme UML illustrant l'exemple

Nous savons que voler() et cancaner() sont les parties de la classe Canard qui varient d’un canard à l’autre.

Pour séparer ces comportements de la classe Canard, nous extrayons ces deux méthodes de la classe et nous créons un nouvel ensemble de classes pour représenter chaque comportement[2].


Canard utilise des attributs de type interface ComportementVol et ComportementCancan (le "bruit" du canard).

Ce sont ces interfaces qui encapsulent le code des méthodes effectuerVol() et effectuerCancan().

Ce sont ces méthodes que nous souhaitons encapsuler, selon le patron de conception stratégie, afin de les rendre interchangeables.

Malgré notre volonté de rendre ces méthodes interchangeables :

  • il reste d'autres méthodes que nous souhaitons conserver communes : ici la méthode nager().
  • et d'autres méthodes que nous souhaitons spécifique à l'implémentation choisie : ici la méthode afficher().
public abstract class Canard {
	ComportementVol comportementVol;
	ComportementCancan comportementCancan;

	public Canard() {
	}

	public abstract void afficher();

	public void effectuerVol() {
		comportementVol.voler();
	}

	public void effectuerCancan() {
		comportementCancan.cancaner();
	}

	public void nager() {
		System.out.println("Tous les canards flottent, même les leurres!");
	}

	public void setComportementVol(ComportementVol comportementVol) {
		this.comportementVol = comportementVol;
	}

	public void setComportementCancan(ComportementCancan comportementCancan) {
		this.comportementCancan = comportementCancan;
	}
}

Maintenant, nous allons spécialiser cette classe Canard en implémentant deux nouvelles classes héritant de Canard. La classe Colvert :

public class Colvert extends Canard {
    public Colvert() {
		comportementVol = new VolerAvecDesAiles();
		comportementCancan = new Cancan();
	}

	public void afficher() {
		System.out.println("Je suis un vrai colvert");
	}
}

Et la classe PrototypeCanard :

public class PrototypeCanard extends Canard {
    public PrototypeCanard() {
        comportementVol = new NePasVoler();
        comportementCancan = new Cancan();
    }
    public void afficher() {
        System.out.println("Je suis un prototype de canard");
    }
}

L'attribut comportementVol est un objet dont la classe implémente l'interface ComportementVol.

public interface ComportementVol {
	public void voler();
}

L'attribut comportementCancan est un objet dont la classe implémente l'interface ComportementCancan.

public interface ComportementCancan {
  public void cancaner() ;
}

Il est alors possible de spécifier autant de ComportementVol et de ComportementCancan que nécessaire, simplement en créant de nouvelle classe implémentant ces deux interfaces. À charge ensuite à ces classes d'implémenter les méthodes voler() ...

public class VolerAvecDesAiles implements ComportementVol {
	public void voler() {
		System.out.println("Je vole !!");
	}
}

public class NePasVoler implements ComportementVol {
	public void voler() {
		System.out.println("Je ne sais pas voler");
	}
}

... et cancaner() pour spécifier le comportement désiré.

public class Cancan implements ComportementCancan {
	public void cancaner() {
		System.out.println("Cancan");
	}
}

Exemple en Smalltalk

Ici, le comportement d'une voiture peut être modifié en fonction de la stratégie de conduite:

ConduiteSport>>avance
  Transcript show: 'à fond à fond'; cr

ConduiteTranquille>>avance
  Transcript show: 'on roule doucement'; cr

Voiture>>modeSport
  strategieConduite := ConduiteSport new

Voiture>>modeTranquille
  strategieConduite := ConduiteTranquille new

Voiture>>avance
  strategieConduite avance

On peut donc écrire:

maVoiture := Voiture new.

maVoiture modeSport.
maVoiture avance. "Affiche 'à fond à fond'"

maVoiture modeTranquille.
maVoiture avance. "Affiche 'on roule doucement'"

Notes et références

  1. (en) Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides, Design Patterns: Elements of Reusable Software, Addison-Wesley, (ISBN 0-201-63361-2), p. 316
  2. Freeman, Eric, 1965-, Freeman, Elisabeth., Sierra, Kathy. et Bates, Bert. (trad. de l'anglais), Design patterns, tête la première, Beijing/Cambridge/Paris etc., O'Reilly, , 637 p. (ISBN 2-84177-350-7 et 978-2-84177-350-3, OCLC 181354957, lire en ligne)

Read other articles:

Katedral Los TequesKatedral Santo Filipus NeriSpanyol: Catedral de San Felipe Nericode: es is deprecated Katedral Los TequesLokasiLos TequesNegaraVenezuelaDenominasiGereja Katolik RomaArsitekturStatusKatedralStatus fungsionalAktifAdministrasiKeuskupanKeuskupan Los Teques Katedral Santo Filipus Neri[1] (Spanyol: Catedral de San Felipe Nericode: es is deprecated )[2] disebut juga Katedral Los Teques[3] adalah sebuah gereja katedral Katolik yang terletak di pusat bersejar...

 

Chronologies Données clés 1811 1812 1813  1814  1815 1816 1817Décennies :1780 1790 1800  1810  1820 1830 1840Siècles :XVIIe XVIIIe  XIXe  XXe XXIeMillénaires :-Ier Ier  IIe  IIIe Chronologies géographiques Afrique Afrique du Sud, Algérie, Angola, Bénin, Botswana, Burkina Faso, Burundi, Cameroun, Cap-Vert, République centrafricaine, Comores, République du Congo, République démocratique du Congo, Côte d'Ivoire, Djibouti, Égyp...

 

Untuk pohon suar, lihat trembesi. Sebuah helikopter Seahawk melepaskan suar Suar atau cerawat (Inggris: flare) adalah salah satu bentuk piroteknik yang menghasilkan cahaya yang sangat terang atau panas tinggi tanpa menghasilkan ledakan. Suar digunakan untuk memberi tanda, penerangan dan alat pertahanan militer. Secara umum, Suar menghasilkan cahaya yang dihasilkan dari pembakaran logam magnesium, kadang-kadang dicampur dengan logam lain untuk menghasilkan warna yang berbeda-beda. Suar kal...

1998 book by Patricia A. McKillip Song for the Basilisk First edition coverAuthorPatricia A. McKillipCover artistKinuko Y. CraftCountryUnited StatesLanguageEnglishGenreFantasyPublisherAce BooksPublication dateSeptember 1, 1998Media typePrintPages314ISBN0-441-00447-4OCLC987642215 Song for the Basilisk is a 1998 fantasy novel by American writer Patricia A. McKillip. It was a Mythopoeic Fantasy Award for Adult Literature finalist in 1999.[1] Summary The sole survivor of a massa...

 

Professional ice hockey team based in Virginia Roanoke Rail Yard DawgsCityRoanoke, VirginiaLeagueSPHLFounded2009; 15 years ago (2009)Home arenaBerglund CenterColorsRoyal blue, gold, white     Owner(s)McGinn family[a]Head coachDan BremnerCaptainMac JansenMediaThe Roanoke TimesFranchise history2009–2014Mississippi Surge2016–presentRoanoke Rail Yard DawgsChampionshipsPlayoff championships1 (2022–23) The Roanoke Rail Yard Dawgs are a professional ice...

 

917

Cette page concerne l'année 917 du calendrier julien. Chronologies Données clés 914 915 916  917  918 919 920Décennies :880 890 900  910  920 930 940Siècles :VIIIe IXe  Xe  XIe XIIeMillénaires :-IIe -Ier  Ier  IIe IIIe Calendriers Romain Chinois Grégorien Julien Hébraïque Hindou Hégirien Persan Républicain modifier L'année 917 est une année commune qui commence un mercredi. Événements Afrique Au Maroc, l'émir de Nekor est...

Questa voce sull'argomento calciatori greci è solo un abbozzo. Contribuisci a migliorarla secondo le convenzioni di Wikipedia. Segui i suggerimenti del progetto di riferimento. Anastasios Chatzīgiovannīs Nazionalità  Grecia Altezza 175 cm Peso 62 kg Calcio Ruolo Attaccante Squadra  Ankaragücü Carriera Giovanili 2013-2016 Panathīnaïkos Squadre di club1 2015-2022 Panathīnaïkos114 (13)[1]2022- Ankaragücü27 (2) Nazionale 2017-2018 Grecia U-2112 (...

 

Bagian dari seri artikel mengenaiEnergi berkelanjutan Ikhtisar Energi berkelanjutan Bahan bakar karbon netral Penghapusan bertahap bahan bakar fosil Penghematan energi Kogenerasi Efisiensi energi Penyimpanan energi Bangunan hijau Pompa panas Tenaga rendah karbon Mikrogenerasi Desain bangunan surya pasif Energi terbarukan Bahan bakar hayati Panas bumi Pembangkit listrik tenaga air Surya Pasang surut Ombak Angin Transportasi berkelanjutan Kendaraan listrik Kendaraan hijau Hibrida plug-in  ...

 

Copa América 2021CONMEBOL Copa América Brasil 2021 Competizione Copa América Sport Calcio Edizione 47ª Organizzatore CONMEBOL Date 13 giugno - 10 luglio 2021[1] Luogo  Brasile(4 città) Partecipanti 10 Impianto/i 5 stadi Risultati Vincitore Argentina(15º titolo) Secondo Brasile Terzo Colombia Quarto Perù Statistiche Miglior giocatore Lionel Messi Miglior marcatore Luis Díaz Lionel Messi (4) Miglior portiere Emiliano Martínez Incontri disputati 28 Gol ...

Азиатский барсук Научная классификация Домен:ЭукариотыЦарство:ЖивотныеПодцарство:ЭуметазоиБез ранга:Двусторонне-симметричныеБез ранга:ВторичноротыеТип:ХордовыеПодтип:ПозвоночныеИнфратип:ЧелюстноротыеНадкласс:ЧетвероногиеКлада:АмниотыКлада:СинапсидыКласс:Мле�...

 

1992 Indian filmMy Dear MuthachanDirected bySathyan AnthikadWritten bySreenivasanProduced byJoy ThomasStarringThilakanMadhurima NarlaJayaramCinematographyVipin MohanEdited byK. RajagopalMusic byJohnsonProductioncompanyJubilee ProductionsDistributed byJubilee ProductionsRelease date 1992 (1992) CountryIndiaLanguageMalayalam My Dear Muthachan (transl. My Dear Grandfather) is a 1992 Malayalam film written by Sreenivasan and directed by Sathyan Anthikad and produced by Joy Thomas. It ...

 

 烏克蘭總理Прем'єр-міністр України烏克蘭國徽現任杰尼斯·什米加尔自2020年3月4日任命者烏克蘭總統任期總統任命首任維托爾德·福金设立1991年11月后继职位無网站www.kmu.gov.ua/control/en/(英文) 乌克兰 乌克兰政府与政治系列条目 宪法 政府 总统 弗拉基米尔·泽连斯基 總統辦公室 国家安全与国防事务委员会 总统代表(英语:Representatives of the President of Ukraine) 总...

هذه مقالة غير مراجعة. ينبغي أن يزال هذا القالب بعد أن يراجعها محرر؛ إذا لزم الأمر فيجب أن توسم المقالة بقوالب الصيانة المناسبة. يمكن أيضاً تقديم طلب لمراجعة المقالة في الصفحة المخصصة لذلك. (أبريل 2023) غراميل الخرم مظيهير الفجةمعلومات عامةنوع المبنى نقوش ثموديةالمنطقة الإدا�...

 

Adjacent sea zone in which a state has special rights Not to be confused with Special economic zone. The world's exclusive economic zones by boundary types and EEZ types An exclusive economic zone (EEZ), as prescribed by the 1982 United Nations Convention on the Law of the Sea, is an area of the sea in which a sovereign state has exclusive rights regarding the exploration and use of marine resources, including energy production from water and wind.[1] It stretches from the outer limit...

 

American college basketball season 1980–81 North Carolina Tar Heels men's basketballNCAA tournament, Runner-upACC tournament championsNational Championship Game, L 50-63 vs. IndianaConferenceAtlantic Coast ConferenceRankingCoachesNo. 6APNo. 6Record29–8 (10–4 ACC)Head coachDean Smith (20th season)Assistant coaches Bill Guthridge (14th season) Eddie Fogler (10th season) Roy Williams (3rd season) Home arenaCarmichael AuditoriumSeasons← 1979–801981–82 ...

Koloni Virginia1607–1776 Bendera Lambang Semboyan: En dat Virginia quintum (Virginia memberikan yang kelima)[1]StatusKoloni Inggris (1607–1707) Koloni Great Britain (1707–1776)Ibu kotaJamestown (1607–1699)Williamsburg (1699–1776)Bahasa yang umum digunakanInggris, rumpun bahasa Siouan, rumpun bahasa Iroquoian, rumpun bahasa AlgonquianAgama AnglikanPemerintahanMonarki konstitusional• 1760–1776 George III (terakhir) Gubernur • 1607 Edward Wingfiel...

 

Aileen RigginNazionalità Stati Uniti Altezza142 cm Tuffi SquadraWomen's Swimming Association Palmarès Competizione Ori Argenti Bronzi Giochi olimpici 1 1 0 Vedi maggiori dettagliNuoto SquadraWomen's Swimming Association Palmarès Competizione Ori Argenti Bronzi Giochi olimpici 0 0 1 Vedi maggiori dettagliStatistiche aggiornate al 21 giugno 2010 Modifica dati su Wikidata · Manuale Aileen Muriel Riggin Soule (Newport, 2 maggio 1906 – Honolulu, 19 ottobre 2002) è stata una nu...

 

This is an archive of past discussions. Do not edit the contents of this page. If you wish to start a new discussion or revive an old one, please do so on the current talk page. Archive 1 Archive 2 Archive 3 New Democratic Party of Canada former leader Audrey McLaughlin New Democratic Party of Canada former leader Audrey McLaughlin is missing a photo, anyone have one? 65.92.180.131 (talk) 03:12, 25 March 2012 (UTC) Polish Socialism Anyone available and willing to help me put together an ar...

Эту страницу предлагается переименовать в «Чемпионат мира по футболу среди команд до 17 лет» или «Чемпионат мира по футболу среди юношей до 17 лет».Пояснение причин и обсуждение — на странице Википедия:К переименованию/7 августа 2023. Пожалуйста, основывайте свои аргум...

 

Pour les articles homonymes, voir Rue de la Paix. 1er, 2e arrtsRue de la Paix La Rue de la Paix par Jean Béraud (1907). Situation Arrondissements 1er2e Quartiers Place-VendômeGaillon Début Place Vendôme Fin Place de l'Opéra Morphologie Longueur 230 m Largeur 22,5 m Historique Ancien nom Rue Napoléon Géocodification Ville de Paris 6911 DGI 6998 Géolocalisation sur la carte : Paris Rue de la Paix modifier  La rue de la Paix est une rue des 1er et 2e arrondissem...