Strategia (suunnittelumalli)

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 6. heinäkuuta 2017 tarkistetusta versiosta . tarkastukset vaativat 11 muokkausta .
strategia
strategia
Tyyppi käyttäytymiseen
Tarkoitus voit käyttää erilaisia ​​liiketoimintasääntöjä tai algoritmeja kontekstista riippuen.
Pätee tapauksissa kun samassa paikassa, riippuen järjestelmän (tai sen ympäristön) nykyisestä tilasta, on käytettävä erilaisia ​​​​algoritmeja
Plussat
  • kapseloimalla erilaisten algoritmien toteutuksen, järjestelmästä tulee riippumaton mahdollisista liiketoimintasääntöjen muutoksista;
  • kutsua kaikkia algoritmeja yhdellä vakiotavalla;
  • ei käytä kytkimiä ja/tai ehdollisia lausekkeita.
Miinukset luomalla lisäluokkia
Aiheeseen liittyvät mallit Silta , mallimenetelmä , sovitin
Kuvattu suunnittelukuvioissa Joo

Strategia ( eng.  Strategy ) on käyttäytymissuunnittelumalli , joka on suunniteltu määrittelemään algoritmiperhe , kapseloimaan jokainen niistä ja varmistamaan niiden vaihdettavuus. Tämän avulla voit valita algoritmin määrittämällä sopivan luokan. Strategiamallin avulla voit muuttaa valittua algoritmia riippumatta sitä käyttävistä asiakasobjekteista .

Tärkeimmät ominaisuudet

Haaste

Valitse sopiva käytettävä algoritmi asiakastyypin (tai käsiteltävän tiedon tyypin mukaan). Jos käytetään sääntöä, jota ei voida muuttaa, strategiamalliin ei tarvitse viitata.

Motiivit

Ratkaisu

Algoritmin valintamenettelyn erottaminen sen toteutuksesta. Tämä mahdollistaa valinnan tekemisen kontekstin perusteella.

Jäsenet

Seuraukset

Toteutus

Algoritmia ( Context) käyttävä luokka sisältää abstraktin luokan ( Strategy), jolla on abstrakti menetelmä, joka määrittää, kuinka algoritmi vedetään. Jokainen johdettu luokka toteuttaa yhden vaaditun version algoritmista.

Huomautus: Algoritmin kutsumenetelmän ei tarvitse olla abstrakti, jos jokin oletuskäyttäytyminen halutaan toteuttaa.

Hyödyllistä tietoa

Käyttö

Microsoft WDF -arkkitehtuuri perustuu tähän malliin . Jokaisessa "ohjain"- ja "laite"-objektissa on järjestelmään ommeltu muuttumaton osa, johon on rekisteröity tietyssä toteutuksessa kirjoitettu muuttuva osa (strategia). Vaihteleva osa voi olla täysin tyhjä, mikä antaa ajurin, joka ei tee mitään, mutta pystyy samalla osallistumaan PnP:hen ja virranhallintaan.

ATL - kirjasto sisältää joukon ketjutusmalliluokkia, jotka ovat strategioita (erilaisia ​​Lock/Unlock-toteutuksia, joita järjestelmän pääluokat sitten käyttävät). Nämä strategiat käyttävät kuitenkin staattista polymorfismia malliparametrin kautta dynaamisen polymorfismin sijaan virtuaalisten menetelmien avulla.

Esimerkkejä

Java esimerkki

Toteutusesimerkki // Tietyn strategian toteuttavan luokan on toteutettava tämä rajapinta // Kontekstiluokka käyttää tätä rajapintaa kutsuakseen tietyn strategiarajapinnan Strategia { int execute ( int a , int b ) ; } // Toteuta algoritmi käyttämällä strategiarajapintaluokkaa ConcreteStrategyAdd implements Strategy { public int execute ( int a , int b ) { Järjestelmä . ulos . println ( "Kutsuttiin ConcreteStrategyAdd's execute()" ); palauttaa a + b ; // Tee lisäys a:lla ja b:llä } } luokka ConcreteStrategySubtract toteuttaa strategian { public int execute ( int a , int b ) { Järjestelmä . ulos . println ( "Kutsuttu ConcreteStrategySubtract's execute()" ); palauttaa a - b ; // Tee vähennyslasku a:lla ja b:llä } } luokka ConcreteStrategyMultiply toteuttaa strategian { public int execute ( int a , int b ) { Järjestelmä . ulos . println ( "Kutsuttiin ConcreteStrategyMultiplyn execute()" ); palauttaa a * b ; // Tee kertolasku a:lla ja b:llä } } // Kontekstiluokka käyttäen strategiarajapintaluokkaa Konteksti { yksityinen strategiastrategia ; _ // Rakentajan julkinen konteksti () { } // Aseta uusi strategia public void setStrategy ( Strategiastrategia ) { this . strategia = strategia ; } public int executeStrategy ( int a , int b ) { paluustrategia . _ suorittaa ( a , b ); } } // Testaa sovellusluokkaa StrategyEsimerkki { public static void main ( String [ ] args ) { Kontekstikonteksti = uusi Konteksti ( ); konteksti . setStrategy ( uusi ConcreteStrategyAdd ()); int tulosA = konteksti . executeStrategy ( 3 , 4 ); konteksti . setStrategy ( uusi ConcreteStrategySubtract ()); int tulosB = konteksti . executeStrategy ( 3 , 4 ); konteksti . setStrategy ( uusi ConcreteStrategyMultiply ()); int tulosC = konteksti . executeStrategy ( 3 , 4 ); Järjestelmä . ulos . println ( "Tulos A : " + tulos A ); Järjestelmä . ulos . println ( "Tulos B : " + tulos B ); Järjestelmä . ulos . println ( "Tulos C : " + tulos C ); } }

Esimerkki C++ :ssa

Toteutusesimerkki #include <iostream> luokan strategia { julkinen : virtuaalinen ~ strategia () {} virtuaalinen tyhjä käyttö () = 0 ; }; luokka Strategia_1 : julkinen strategia { julkinen : void use (){ std :: cout << "Strategia_1" << std :: endl ; } }; luokka Strategia_2 : julkinen strategia { julkinen : void use (){ std :: cout << "Strategia_2" << std :: endl ; } }; luokka Strategia_3 : julkinen strategia { julkinen : void use (){ std :: cout << "Strategia_3" << std :: endl ; } }; luokan konteksti { suojattu : strategia * toiminta ; julkinen : virtuaalinen ~ Konteksti () {} virtuaalinen tyhjä käyttöStrategy () = 0 ; virtuaalinen void setStrategy ( Strategy * v ) = 0 ; }; luokan asiakas : julkinen konteksti { julkinen : void useStrategy () { toiminta -> käyttö (); } void setStrategy ( Strategia * o ) { toiminta = o ; } }; int main ( int /*argc*/ , char * /*argv*/ []) { Asiakas customClient ; strategia_1 str1 ; Strategia_2 str2 ; Strategia_3 str3 ; customClient . setStrategy ( & str1 ); customClient . useStrategy (); customClient . setStrategy ( & str2 ); customClient . useStrategy (); customClient . setStrategy ( & str3 ); customClient . useStrategy (); paluu 0 ; } Toteutusesimerkki (malliparametri) #include <iostream> rakennestrategia_1 _ { void use (){ std :: cout << "Strategia_1" << std :: endl ; }; }; rakennestrategia_2 _ { void use (){ std :: cout << "Strategia_2" << std :: endl ; }; }; rakennestrategia_3 _ { void use (){ std :: cout << "Strategia_3" << std :: endl ; }; }; malli < classOperation > _ struct Asiakas : julkinen käyttö { void useStrategy () { tämä -> käytä (); } }; int main ( int /*argc*/ , char * /*argv*/ []) { Asiakas < Strategy_1 > customClient1 ; customClient1 . useStrategy (); Asiakas < Strategy_2 > customClient2 ; customClient2 . useStrategy (); Asiakas < Strategy_3 > customClient3 ; customClient3 . useStrategy (); paluu 0 ; }

Esimerkki C# :ssa

Toteutusesimerkki käyttäen System ; nimitila DesignPatterns.Behavioral.Strategy { // Tietyn strategian toteuttavan luokan on perittävä tämä rajapinta // Kontekstiluokka käyttää tätä rajapintaa kutsuakseen tietyn strategian julkisen käyttöliittymän IStrategy { void Algorithm (); } // Ensimmäinen konkreettinen toteutusstrategia. public class ConcreteStrategy1 : IStrategy { public void Algorithm () { Konsoli . WriteLine ( "Strategiaalgoritmi 1 on käynnissä." ); } } // Toinen konkreettinen toteutusstrategia. // Toteutuksia voi olla niin monta kuin haluat. public class ConcreteStrategy2 : IStrategy { public void Algorithm () { Konsoli . WriteLine ( "Strategiaalgoritmi 2 on käynnissä." ); } } // Konteksti, joka käyttää strategiaa ongelmansa ratkaisemiseen. public class Konteksti { // Viittaus IStrategy-liittymään // mahdollistaa automaattisen siirtymisen tiettyjen toteutusten välillä // (eli tämä on tietyn strategian valinta). yksityinen IStrategy_strategy ; _ // Kontekstin rakentaja. // Alustaa objektin strategialla. public Context ( IStrategy - strategia ) { _strategia = strategia ; } // Strategian asettamismenetelmä. // Käytetään strategian muuttamiseen ajon aikana. // C#:ssa se voidaan toteuttaa myös tietueen ominaisuutena. public void SetStrategy ( IStrategy strategia ) { _strategy = strategia ; } // Jokin kontekstitoiminto, joka valitsee // strategian ja käyttää sitä tehtävänsä suorittamiseen. public void ExecuteOperation () { _strategia . algoritmi (); } } // Sovellusluokka. // Toimii kontekstiasiakkaana tässä esimerkissä. julkinen staattinen luokka Ohjelma { // <yhteenveto> // Ohjelman aloituspiste. // </summary> public static void Main () { // Luo konteksti ja alusta se ensimmäisellä strategialla. Kontekstikonteksti = uusi konteksti ( uusi ConcreteStrategy1 ( )); // Suorita kontekstitoiminto, joka käyttää ensimmäistä strategiaa. konteksti . ExecuteOperation (); // Korvaa ensimmäinen strategia toisella kontekstissa. konteksti . SetStrategy ( uusi ConcreteStrategy2 ()); // Suorita kontekstitoiminto, joka käyttää nyt toista strategiaa. konteksti . ExecuteOperation (); } } }

Esimerkkejä kirjasta D

Toteutusesimerkki tuonti std . stdio ; käyttöliittymä IStrategy { int Toiminto ( int a , int b ); } class TAlisäys : IStrategy { public int Toiminto ( int a , int b ) { return a + b ; } } luokka TSvähennys : IStrategy { julkinen int Toimi ( int a , int b ) { return a - b ; } } class TContextet { yksityinen : int a , b ; IStrategy- strategia ; public : void SetAB ( int a , int b ) { TContexet . a = a ; TContextet . b = b ; }; void SetStrategy ( IStrategy strategia ) { TContexet . strategia = strategia ; } int Toimi ( ) { paluustrategia . Toiminta ( a , b ); } } void main () { TContexet konteksti = new TContexet ; konteksti . SetAB ( 10 , 5 ); konteksti . SetStrategy ( uusi TAddition ); writeln ( konteksti.Toiminto ( ) ); // viisitoista konteksti . SetStrategy ( uusi TSubtraction ); writeln ( konteksti.Toiminto ( ) ); // 5 }

Esimerkki Delphissä

Toteutusesimerkki ohjelma Strategy_pattern ; {$APPTYPE CONSOLE} tyyppi IStrategy = käyttöliittymä [ '{6105F24C- E5B2-47E5 -BE03-835A894DEB42}' ] toimintoalgoritmi ; loppu ; TConcreteStrategy1 = luokan ( TInterfacedObject , IStrategy ) julkinen menettelyalgoritmi ; _ loppu ; menettely TConcreteStrategy1 . algoritmi ; begin Writeln ( 'TConcreteStrategy1.Algorithm' ) ; loppu ; tyyppi TConcreteStrategy2 = luokan ( TInterfacedObject , IStrategy ) julkinen toimintoalgoritmi ; _ loppu ; menettely TConcreteStrategy2 . algoritmi ; begin Writeln ( 'TConcreteStrategy2.Algorithm' ) ; loppu ; tyyppi TContext = luokka yksityinen FStrategy : IStrategy ; julkinen menettely ContextMethod ; omaisuusstrategia : IStrategy lue FStrategy kirjoittaa FStrategy ; _ loppu ; menettely TContext . ContextMethod ; aloita FStrategy . algoritmi ; loppu ; var Konteksti : TContext ; begin Context := TContext . luoda ; kokeile kontekstia . Strategia := TConcreteStrategy1 . luoda ; Konteksti . ContextMethod ; Konteksti . Strategia := TConcreteStrategy2 . luoda ; Konteksti . ContextMethod ; lopuksi konteksti . Ilmainen ; loppu ; loppua .

Javascript- esimerkkejä

Toteutusesimerkki // "rajapinnan" strategia funktio Strategia () { tämä . exec = funktio () {}; }; // toteuttaa strategia // näytä viesti selaimen tilapalkissa // (kaikki selaimet eivät tue) function StrategyWindowStatus () { this . exec = function ( viesti ) { ikkuna . tila = viesti ; }; }; StrategyWindowStatus . prototyyppi = uusi strategia (); StrategyWindowStatus . prototyyppi . konstruktori = StrategyWindowStatus ; // näytä viesti ponnahdusikkunan kautta // (selain voi estää sen) function StrategyNewWindow () { this . exec = function ( viesti ) { var win = ikkuna . avaa ( "" , "_blank" ); voittaa . asiakirja . kirjoittaa ( "<html>" + viesti + "</html>" ); }; }; StrategiaNewWindow . prototyyppi = uusi strategia (); StrategiaNewWindow . prototyyppi . konstruktori = StrategyNewWindow ; // näytä viesti käyttämällä modaalista ikkunatoimintoa StrategyAlert ( ) { this . exec = function ( viesti ) { hälytys ( viesti ); }; }; Strategiahälytys . prototyyppi = uusi strategia (); Strategiahälytys . prototyyppi . rakentaja = Strategy Alert ; // Konteksti function Konteksti ( strategia ) { this . exec = funktio ( viesti ) { strategia . exec ( viesti ); }; } // Käyttö var showInWindowStatus = new Context ( new StrategyWindowStatus () ); var showInNewWindow = new Context ( new StrategyNewWindow () ); var showInAlert = new Context ( new StrategyAlert () ); showInWindowStatus . exec ( "viesti" ); showInNew Window . exec ( "viesti" ); showInAlert . exec ( "viesti" );

Esimerkkejä PHP :ssä

Toteutusesimerkki <?php - käyttöliittymä NamingStrategy { function createName ( $tiedostonimi ); } class ZipFileNamingStrategy toteuttaa NamingStrategy { function createName ( $tiedostonimi ) { return "http://downloads.foo.bar/ { $tiedostonimi } .zip" ; } } class TarGzFileNamingStrategy toteuttaa NamingStrategy { function createName ( $tiedostonimi ) { return "http://downloads.foo.bar/ { $tiedostonimi } .tar.gz" ; } } class Konteksti { yksityinen $nimistrategia ; function __construct ( NamingStrategy $strategia ) { $this -> namingStrategy = $strategia ; } function execute () { $url [] = $this -> namingStrategy -> createName ( "Calc101" ); $url [] = $this -> nameingStrategy -> createName ( "Stat2000" ); palauttaa $url ; } } if ( strstr ( $_SERVER [ "HTTP_USER_AGENT" ], "Win" )) $context = new Context ( new ZipFileNamingStrategy ()); else $context = uusi konteksti ( uusi TarGzFileNamingStrategy ()); $context -> suorita (); ?>

Esimerkki Pythonissa 2.7

Toteutusesimerkki luokka Ihmiset ( objekti ): työkalu = Ei mitään def __init__ ( itse , nimi ): itse . nimi = nimi def setTool ( itse , työkalu ): itse . työkalu = työkalu def kirjoittaa ( itse , teksti ): itse . työkalu . kirjoittaa ( itse . nimi , teksti ) class ToolBase : """ `Kirjoitustyökalu` Algoritmiperhe """ def write ( itse , nimi , teksti ): nosta NotImplementedError () luokka PenTool ( ToolBase ): """Kynä""" def write ( itse , nimi , teksti ): print u ' %s (kynä) %s ' % ( nimi , teksti ) luokka BrushTool ( ToolBase ): """Brush""" def write ( itse , nimi , teksti ): tulosta u ' %s (siveltimellä) %s ' % ( nimi , teksti ) luokan opiskelija ( ihmiset ): """Oppilas""" työkalu = PenTool () luokan Painter ( Ihmiset ): """Taiteilija""" työkalu = BrushTool () maksimi = Opiskelija ( u 'Maksimi' ) maksimi . kirjoittaa ( u 'Kirjoitan luennon strategiamallista' ) # Maxim (kynällä) Kirjoitan luennon strategiamallista sasha = Taidemaalari ( u 'Sasha' ) sasha . kirjoittaa ( u 'Piirrän kuvan strategiakuviolle' ) # Sasha (siveltimellä) Piirrän kuvan strategiakuviolle # Sasha päätti tulla Sashan opiskelijaksi . setTool ( PenTool ()) sasha . kirjoittaa ( u 'Ei, kirjoitan mieluummin synopsiksen' ) # Sasha (kynällä) Ei, kirjoitan mieluummin yhteenvedon

Esimerkki Rubyssa

Toteutusesimerkki vaatii "käyttöliittymän" strategia = käyttöliittymä { pakolliset_menetelmät :käyttö } luokka StrategyOne def use laittaa "Strategy one" pään toteuttaa Strategy end luokka StrategyTwo def use laittaa "Strategy kaksi" loppuun toteuttaa Strategy end luokka StrategyThree def use laittaa "Strategia kolme" loppuun toteuttaa strategian loppuun luokka Konteksti attr_accessor :strategia def alusta strategia @strategia = strategia loppu def useStrategy strategia . käytä loppupäätä _ konteksti = konteksti . uusi strategia yksi . uusi konteksti . käytä strategiaa konteksti . strategia = strategia kaksi . uusi konteksti . käytä strategiaa konteksti . strategia = StrategyThree . uusi konteksti . käytä strategiaa

Tietolähteet

  • E. Gamma, R. Helm, R. Johnson, J. Vlissides . Olio-suunnittelun tekniikat. Suunnittelumallit = Suunnittelumallit: Uudelleenkäytettävän olio-ohjelmiston elementit. - Pietari. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (myös ISBN 5-272-00355-1 )
  • Shalloway , Alan, Trott , James, R. Suunnittelukuvioita. Uusi lähestymistapa olio-analyysiin ja suunnitteluun : Per. englannista. -M .: Williams Publishing House, 2002. -288 s. ISBN 5-8459-0301-7
  • Grand, M. Design Patterns in Java: Per. englannista .. - M . : Uusi tieto, 2004. - S. 559. - ISBN 5-94735-047-5 .