Strategie (návrhový vzor)

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 6. července 2017; kontroly vyžadují 11 úprav .
Strategie
strategie
Typ behaviorální
Účel umožňuje používat různá obchodní pravidla nebo algoritmy v závislosti na kontextu.
Platí v případech když na stejném místě, v závislosti na aktuálním stavu systému (nebo jeho prostředí), musí být použity různé algoritmy
profesionálové
  • zapouzdřením implementace různých algoritmů se systém stává nezávislým na případných změnách obchodních pravidel;
  • volání všech algoritmů jedním standardním způsobem;
  • nepoužívání přepínačů a/nebo podmíněných příkazů.
Mínusy vytváření dalších tříd
Související šablony Most , metoda šablony , adaptér
Popsáno v Návrhové vzory Ano

Strategie ( angl.  Strategy ) je behaviorální návrhový vzor určený k definování rodiny algoritmů , zapouzdření každého z nich a zajištění jejich zaměnitelnosti. To vám umožní vybrat algoritmus definováním příslušné třídy. Šablona strategie umožňuje změnit vybraný algoritmus bez ohledu na objekty klienta , které jej používají.

Klíčové vlastnosti

Výzva

Podle typu klienta (nebo podle typu zpracovávaných dat) vyberte vhodný algoritmus, který chcete použít. Pokud se použije pravidlo, které nepodléhá změnám, není třeba odkazovat na vzor strategie.

Motivy

Řešení

Oddělení postupu výběru algoritmu od jeho implementace. To umožňuje provádět výběr na základě kontextu.

Členové

Důsledky

Implementace

Třída, která používá algoritmus ( Context), zahrnuje abstraktní třídu ( Strategy), která má abstraktní metodu, která definuje, jak je algoritmus vyvolán. Každá odvozená třída implementuje jednu požadovanou verzi algoritmu.

Poznámka: Pokud má být implementováno nějaké výchozí chování, metoda volání algoritmu nemusí být abstraktní.

Užitečné informace

Použití

Architektura Microsoft WDF je založena na tomto vzoru. Každý objekt „ovladač“ a „zařízení“ má v systému všitou neměnnou část, ve které je registrována proměnlivá část (strategie) zapsaná v konkrétní implementaci. Proměnlivá část může být zcela prázdná, což dá ovladač, který nic nedělá, ale zároveň je schopen se podílet na PnP a správě napájení.

Knihovna ATL obsahuje sadu tříd modelu vláken, které jsou strategiemi (různé implementace Lock / Unlock, které pak používají hlavní třídy systému). Tyto strategie však využívají spíše statický polymorfismus prostřednictvím parametru šablony než dynamický polymorfismus prostřednictvím virtuálních metod.

Příklady

Příklad Java

Příklad implementace // Třída, která implementuje konkrétní strategii, musí implementovat toto rozhraní // Třída kontextu používá toto rozhraní k vyvolání rozhraní konkrétní strategie Strategy { int execute ( int a , int b ) ; } // Implementujte algoritmus pomocí třídy rozhraní strategie ConcreteStrategyAdd implements Strategy { public int vykonat ( int a , int b ) { System . ven . println ( "Vyvolána funkce ConcreteStrategyAdd's execute()" ); vrátit a + b ; // Proveďte sčítání pomocí a a b } } class ConcreteStrategySubtract implementuje strategii { public int vykonat ( int a , int b ) { System . ven . println ( "Volaná metoda ConcreteStrategySubtract's execute()" ); vrátit a - b ; // Proveďte odčítání s aab } } class ConcreteStrategyMultiply implementuje strategii { public int vykonat ( int a , int b ) { System . ven . println ( "Calected ConcreteStrategyMultiply's execute()" ); vrátit a * b ; // Proveďte násobení pomocí a a b } } // Kontextová třída používající strategii rozhraní class Context { soukromá strategie ; _ // Konstruktor public Context () { } // Nastavení nové strategie public void setStrategy ( Strategie strategy ) { this . strategie = strategie ; } public int vykonatStrategie ( int a , int b ) { strategie návratu . provést ( a , b ); } } // Testování třídy aplikace StrategyExample { public static void main ( String [] args ) { Kontext kontextu = new Context (); kontextu . setStrategy ( new ConcreteStrategyAdd ()); int vysledekA = kontext . vykonatStrategie ( 3 , 4 ); kontextu . setStrategy ( new ConcreteStrategySubtract ()); int vysledekB = kontext . vykonatStrategie ( 3 , 4 ); kontextu . setStrategy ( new ConcreteStrategyMultiply ()); int vysledekC = kontext . vykonatStrategie ( 3 , 4 ); Systém . ven . println ( "Výsledek A: " + výsledek A ); Systém . ven . println ( "Výsledek B: " + výsledek B ); Systém . ven . println ( "Výsledek C: " + výsledek C ); } }

Příklad v C++

Příklad implementace #include <iostream> třída Strategie { veřejnost : virtuální ~ Strategie () {} virtuální void použití () = 0 ; }; třída Strategie_1 : veřejná Strategie { veřejnost : void use (){ std :: cout << "Strategie_1" << std :: endl ; } }; třída Strategie_2 : veřejná Strategie { veřejnost : void use (){ std :: cout << "Strategie_2" << std :: endl ; } }; třída Strategie_3 : veřejná Strategie { veřejnost : void use (){ std :: cout << "Strategie_3" << std :: endl ; } }; Kontext třídy { chráněno : strategie * provoz ; veřejnost : virtuální ~ kontext () {} virtual void useStrategy () = 0 ; virtuální void setStrategy ( Strategie * v ) = 0 ; }; třída Klient : veřejný kontext { veřejnost : void useStrategy () { operace -> použití (); } void setStrategy ( Strategie * o ) { operace = o ; } }; int main ( int /*argc*/ , char * /*argv*/ []) { Klient customClient ; strategie_1 str1 ; Strategie_2 str2 ; Strategie_3 str3 ; customClient . setStrategy ( & str1 ); customClient . useStrategy (); customClient . setStrategy ( & str2 ); customClient . useStrategy (); customClient . setStrategy ( & str3 ); customClient . useStrategy (); návrat 0 ; } Příklad implementace (parametr šablony) #include <iostream> struct Strategy_1 { void use (){ std :: cout << "Strategie_1" << std :: endl ; }; }; struct Strategy_2 { void use (){ std :: cout << "Strategie_2" << std :: endl ; }; }; struct Strategy_3 { void use (){ std :: cout << "Strategie_3" << std :: endl ; }; }; šablona < classOperation > _ struct Klient : veřejný provoz { void useStrategy () { toto -> použít (); } }; int main ( int /*argc*/ , char * /*argv*/ []) { Klient < Strategie_1 > customClient1 ; customClient1 . useStrategy (); Klient < Strategie_2 > customClient2 ; customClient2 . useStrategy (); Klient < Strategie_3 > customClient3 ; customClient3 . useStrategy (); návrat 0 ; }

Příklad v C#

Příklad implementace pomocí System ; jmenný prostor DesignPatterns.Behavioral.Strategy { // Třída, která implementuje konkrétní strategii, musí toto rozhraní zdědit // Třída kontext používá toto rozhraní k vyvolání konkrétní strategie public interface ISstrategy { void Algorithm (); } // První konkrétní implementační strategie. public class ConcreteStrategy1 : IStrategy { public void Algorithm () { Console . WriteLine ( "Strategický algoritmus 1 běží." ); } } // Druhá konkrétní implementační strategie. // Implementací může být tolik, kolik chcete. public class ConcreteStrategy2 : IStrategy { public void Algorithm () { Console . WriteLine ( "Strategický algoritmus 2 běží." ); } } // Kontext, který používá strategii k řešení svého problému. public class Context { // Odkaz na rozhraní ISstrategy // umožňuje automatické přepínání mezi konkrétními implementacemi // (jinými slovy jde o volbu konkrétní strategie). private ISstrategy_strategy ; _ // Konstruktor kontextu. // Inicializuje objekt se strategií. public Context ( Strategy strategy ) { _strategy = strategie ; } // Metoda pro nastavení strategie. // Používá se ke změně strategie za běhu. // V C# to může být také implementováno jako vlastnost záznamu. public void SetStrategy ( strategie ISstrategy ) { _strategy = strategie ; } // Některé kontextové funkce, které volí // strategii a používají ji ke splnění svého úkolu. public void ExecuteOperation () { _strategy . algoritmus (); } } // Třída aplikace. // V tomto příkladu funguje jako kontextový klient. public static class Program { // <summary> // Vstupní bod programu. // </summary> public static void Main () { // Vytvořte kontext a inicializujte jej pomocí první strategie. Kontext kontextu = new Context ( new ConcreteStrategy1 ()); // Proveďte kontextovou operaci, která používá první strategii. kontextu . ExecuteOperation (); // Nahraďte v kontextu první strategii druhou. kontextu . SetStrategy ( new ConcreteStrategy2 ()); // Proveďte kontextovou operaci, která nyní používá druhou strategii. kontextu . ExecuteOperation (); } } }

Příklady v D

Příklad implementace import std . stdio ; interface ISstrategie { int Akce ( int a , int b ); } class TAddition : ISstrategie { public int Akce ( int a , int b ) { return a + b ; } } class TOdečtení : IStrategie { public int Akce ( int a , int b ) { return a - b ; } } class TContexet { private : int a , b ; strategie ; strategie ; public : void SetAB ( int a , int b ) { TContexet . a = a ; TContextet . b = b ; }; void SetStrategy ( strategie ISstrategy ) { TContexet . strategie = strategie ; } int Akce () { strategie návratu . Akce ( a , b ); } } void main () { TContexet context = new TContexet ; kontextu . SetAB ( 10,5 ) ; _ kontextu . SetStrategy ( nový TAddition ); writeln ( kontext.Akce ( ) ); // patnáct kontextu . SetStrategy ( new TSuttraction ); writeln ( kontext.Akce ( ) ); // 5 }

Příklad v Delphi

Příklad implementace program Strategie_vzor ; {$APPTYPE KONZOLE} type ISstrategy = interface [ '{6105F24C-E5B2-47E5-BE03-835A894DEB42}' ] procedure Algorithm ; konec ; TConcreteStrategy1 = class ( TInterfacedObject , ISstrategy ) veřejná procedura Algoritmus ; konec ; postup TConcreteStrategy1 . algoritmus ; begin Writeln ( 'TConcreteStrategy1.Algorithm' ) ; konec ; typ TConcreteStrategy2 = class ( TInterfacedObject , ISstrategy ) veřejná procedura Algoritmus ; konec ; postup TConcreteStrategy2 . algoritmus ; begin Writeln ( 'TConcreteStrategy2.Algorithm' ) ; konec ; type TContext = class private FStrategy : IStrategy ; veřejné řízení ContextMethod ; vlastnost Strategie : ISstrategie číst FStrategie zápis FStrategie ; konec ; postup TContext . ContextMethod ; začít FStrategy . algoritmus ; konec ; var Context : TContext ; begin Context := TContext . vytvořit ; zkuste kontext . Strategie := TConcreteStrategy1 . vytvořit ; Souvislosti . ContextMethod ; Souvislosti . Strategie := TConcreteStrategy2 . vytvořit ; Souvislosti . ContextMethod ; konečně Kontext . zdarma ; konec ; konec .

Příklady Javascriptu

Příklad implementace // "rozhraní" Strategie funkce Strategie () { toto . exec = funkce () {}; }; // implementovat strategii // zobrazí zprávu ve stavovém řádku prohlížeče // (nepodporováno všemi prohlížeči) function StrategyWindowStatus () { this . exec = funkce ( zpráva ) { okno . stav = zpráva ; }; }; StrategyWindowStatus . prototyp = nová strategie (); StrategyWindowStatus . prototyp . konstruktor = StrategyWindowStatus ; // zobrazit zprávu přes vyskakovací okno // (může být blokováno prohlížečem) function StrategyNewWindow () { this . exec = funkce ( zpráva ) { var win = okno . otevřít ( "" , "_blank" ); vyhrát _ dokument . napište ( "<html>" + zpráva + "</html>" ); }; }; StrategieNovéOkno . prototyp = nová strategie (); StrategieNovéOkno . prototyp . konstruktor = StrategyNewWindow ; // zobrazit zprávu pomocí funkce modálního okna StrategyAlert () { this . exec = funkce ( zpráva ) { upozornění ( zpráva ); }; }; Strategické upozornění . prototyp = nová strategie (); Strategické upozornění . prototyp . konstruktor = Strategy Alert ; // Kontext funkce Kontext ( strategie ) { this . exec = funkce ( zpráva ) { strategie . exec ( zpráva ); }; } // Použití var showInWindowStatus = new Context ( new StrategyWindowStatus () ); var showInNewWindow = new Context ( new StrategyNewWindow () ); var showInAlert = new Context ( new StrategyAlert () ); showInWindowStatus . exec ( "zpráva" ); showInNewWindow . exec ( "zpráva" ); showInAlert . exec ( "zpráva" );

Příklady v PHP

Příklad implementace <?php interface NamingStrategy { function createName ( $filename ); } class ZipFileNamingStrategy implementuje NamingStrategy { function createName ( $filename ) { return "http://downloads.foo.bar/ { $filename } .zip" ; } } class TarGzFileNamingStrategy implementuje NamingStrategy { function createName ( $filename ) { return "http://downloads.foo.bar/ { $filename } .tar.gz" ; } } class Context { private $namingStrategy ; function __construct ( Strategie názvů $strategie ) { $this -> Strategie názvů = $strategie ; } funkce vykonat () { $url [] = $this -> namingStrategy -> createName ( "Calc101" ); $url [] = $this -> namingStrategy -> createName ( "Stat2000" ); return $url ; } } if ( strstr ( $_SERVER [ "HTTP_USER_AGENT" ], "Win" )) $context = new Context ( new ZipFileNamingStrategy ()); else $context = new Context ( new TarGzFileNamingStrategy ()); $kontext -> vykonat (); ?>

Příklad v Pythonu 2.7

Příklad implementace třída Lidé ( objekt ): nástroj = Žádný def __init__ ( self , jméno ): self . jméno = jméno def setTool ( self , tool ): self . nástroj = nástroj def psát ( self , text ): self . nástroj . napsat ( vlastní jméno , text ) _ class ToolBase : """ `Nástroj pro zápis` Rodina algoritmů """ def write ( self , name , text ): raise NotImplementedError () class PenTool ( ToolBase ): """Pero""" def write ( self , name , text ): print u ' %s (pero) %s ' % ( name , text ) class BrushTool ( ToolBase ): """Štětec""" def write ( self , name , text ): print u ' %s (se štětcem) %s ' % ( name , text ) třída Student ( Lidé ): nástroj """Student""" = PenTool () class Painter ( People ): """Umělec""" nástroj = BrushTool () maxim = Student ( u 'Maxim' ) maxim . napište ( u 'Píšu přednášku o vzoru Strategie' ) # Maxim (perem) Píšu přednášku o vzoru Strategie sasha = Malíř ( u 'Sasha' ) sasha . napište ( u 'Kreslím ilustraci vzoru Strategie' ) # Sasha (štětcem) Kreslím ilustraci vzoru Strategie # Sasha se rozhodl stát studentem sasha . setTool ( PenTool ()) sasha . pište ( u 'Ne, radši bych napsal synopsi' ) # Sasha (perem) Ne, radši bych napsal souhrn

Příklad v Ruby

Příklad implementace vyžadovat "rozhraní" strategie = rozhraní { požadované_metody :použití } class StrategyOne def use klade "Strategie jedna" konec implementuje Strategie konec class StrategyTwo def use klade "Strategie dva" end implementuje Strategy end class StrategyThree def use klade "Strategie tři" end implementuje Strategy end class Kontext attr_accessor :strategie def inicializovat strategii @strategy = strategie end def useStrategy strategy . použít konec konec kontext = kontext . nová strategie jedna . nový kontext . useStrategy kontextu . strategie = strategie dvě . nový kontext . useStrategy kontextu . strategie = StrategieTři . nový kontext . useStrategy

Zdroje informací

  • E. Gamma, R. Helm, R. Johnson, J. Vlissides . Techniky objektově orientovaného navrhování. Design Patterns = Design Patterns: Prvky opakovaně použitelného objektově orientovaného softwaru. - Petrohrad. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (také ISBN 5-272-00355-1 )
  • Shalloway , Alan, Trott , James, R. Návrhové vzory. Nový přístup k objektově orientované analýze a návrhu : Per. z angličtiny. -M .: Williams Publishing House, 2002. -288 s. ISBN 5-8459-0301-7
  • Grand, M. Návrhové vzory v Javě: Per. z angličtiny .. - M . : Nové poznatky, 2004. - S. 559. - ISBN 5-94735-047-5 .