JavaRush /Java Blog /Random-TK /Dizaýn nusgasy “Strategiýa”

Dizaýn nusgasy “Strategiýa”

Toparda çap edildi
Salam! Öňki leksiýalarda “dizaýn nagşy” ýaly düşünje eýýäm duş geldik. Forgatdan çykaran bolsaňyz, size ýatladalyň: bu termin programmirlemekde umumy meseläniň belli bir standart çözgüdini aňladýar. “Strategiýa” dizaýn nusgasy - 1JavaRush-da köplenç islendik soraga diýen ýaly jogap Googled bolup biler diýýäris. Şonuň üçin kimdir biri siziňki ýaly meseläni eýýäm üstünlikli çözüp biler. Şeýlelik bilen, nagyşlar iň köp ýaýran meseleleriň ýa-da meseleleri çözmegiň usullarynyň wagtlaýyn synagdan geçirilýän we synagdan geçen çözgütleridir. Bular gaty “welosipedler”, hiç hili ýagdaýda özüňizi oýlap tapmagyň zerurlygy ýok, ýöne olary nädip we haçan ulanmalydygyny bilmelisiňiz :) Nagyşlaryň ýene bir meselesi arhitekturany ýeke-täk standartlara çykarmakdyr. Başga biriniň koduny okamak aňsat iş däl! Her kim muny başgaça ýazýar, sebäbi şol bir meseläni köp tarapdan çözüp bolýar. Patternöne nagyşlaryň ulanylmagy dürli programmistlere koduň her setirine göz aýlamazdan (ilkinji gezek görseler-de!) Programmanyň logikasyna düşünmäge mümkinçilik berýär, bu gün “Strategiýa” diýilýän iň ýaýran nagyşlaryň birine serederis. “Strategiýa” dizaýn nusgasy - 2Awtoulag obýekti bilen işjeň işleýän programma ýazýandygymyzy göz öňüne getireliň. Bu ýagdaýda, programmamyzyň takyk ýerine ýetirýän işi hem möhüm däl. AutoMunuň üçin bir ene-atalar synpy we üç çaga synpy bilen miras ulgamyny döretdik Sedan: Truckwe F1Car.
public class Auto {

   public void gas() {
       System.out.println("Едем вперед");
   }

   public void stop() {

       System.out.println("Тормозим!");
   }
}

public class Sedan extends Auto {
}

public class Truck extends Auto {
}

public class F1Car extends Auto {
}
Üç çaga synpynyň hemmesi ene-atadan iki sany adaty usuly miras alýar - gas()we stop() biziň programmamyz gaty ýönekeý: awtoulaglar diňe öňe hereket edip we tormozlap bilýärler. Işimizi dowam etdirip, awtoulaglara täze usul - fill()ýangyç guýmak kararyna geldik. Ene-atalar synpyna goşalyň Auto:
public class Auto {

   public void gas() {
       System.out.println("Едем вперед");
   }

   public void stop() {

       System.out.println("Тормозим!");
   }

   public void fill() {
       System.out.println("Заправить бензин!");
   }
}
Şeýle ýönekeý ýagdaýda problemalar ýüze çykyp biljege meňzeýärmi? Aslynda, olar eýýäm ýüze çykdy ... “Strategiýa” dizaýn nusgasy - 3
public class ChildrenBuggies extends Auto {

   public void fill() {

       //хм... Это детский багги, его не надо заправлять :/
   }
}
Programmamyzda umumy düşünjä laýyk gelmeýän bir awtoulag peýda boldy - çagalaryň ýalňyşlygy. Pedal bilen işleýän ýa-da radio bilen dolandyrylýan bolup biler, ýöne bir zady anyk bilýäris - oňa benzin goýjak ýer ýok. Miras meýilnamamyz, hatda zerur däl synplara umumy usullary bermegimize sebäp boldy. Şeýle ýagdaýda näme etmeli? Mysal üçin, fill()synpda usuly ýok edip bilersiňiz ChildrenBuggies, buggy ýangyç guýjak bolanyňyzda hiç zat bolmaz:
public class ChildrenBuggies extends Auto {

   @Override
   public void fill() {
       System.out.println("Игрушечную машину нельзя заправить!");
   }
}
Emma bu çözgüdi, iň bolmanda koduň köpeldilmegi sebäpli üstünlikli diýip atlandyryp bolmaz. Mysal üçin, synplaryň köpüsinde ene-atalar synpyndan bir usul ulanylar, ýöne beýleki synplar ony ýok etmäge mejbur bolarlar. 15 synpymyz bar bolsa we 5-6-da özümizi alyp barşymyzy üýtgetmäge mejbur bolsak, kod köpeltmek gaty giň bolar. Belki interfeýsler bize kömek edip biler? Mysal üçin, bu:
public interface Fillable {

   public void fill();
}
FillableBir usul bilen interfeýs dörederis fill(). Şoňa laýyklykda ýangyç guýulmaly awtoulaglar bu interfeýsi durmuşa geçirer, ýöne beýleki awtoulaglar (mysal üçin, buggymyz) amala aşyrmaz. Emma bu wariant bize-de laýyk bolmaz. Biziň synp iýerarhiýamyz geljekde gaty köp mukdarda ösüp biler (dünýäde näçe dürli awtoulag bardygyny göz öňüne getiriň). Öňki miras opsiýasyny terk etdik, sebäbi ýok etmek islemedik fill(). Bu ýerde ony her synpda durmuşa geçirmeli bolarys! Olardan 50-si bar bolsa näme etmeli? Programmamyza ýygy-ýygydan üýtgeşmeler girizilse (we hakyky programmalarda bu hemişe diýen ýaly bolar!), 50 synpyň arasynda dilimizi asyp, olaryň hersiniň özüni alyp barşyny üýtgetmeli bolarys. Soňunda näme etmeli? Meselämizi çözmek üçin başga ýol saýlalyň. .Agny, synpymyzyň özüni alyp barşyny synpyň özünden aýyralyň. Bu näme many berýär? Bilşiňiz ýaly, islendik obýektiň ýagdaýy (maglumatlar toplumy) we özüni alyp barşy (usullar toplumy) bar. Maşyn synpymyzyň özüni alyp barşy üç usuldan ybarat gas()- stop()we fill(). Ilkinji iki usul gowy. Emma üçünji usuly synpyň daşynda geçireris Auto. Bu özüňi alyp barşyň synpdan aýrylmagy bolar (has takygy, özüni alyp barşyň diňe bir bölegini aýyrýarys - ilkinji iki usul öz ýerinde galýar). Usulymyzy nirä göçürmeli fill()? Derrew hiç zat kellä gelenok: / Ol düýbünden öz ýerinde ýalydy. Aýry-aýry interfeýslere geçireris - FillStrategy!
public interface FillStrategy {

   public void fill();
}
Näme üçin bu interfeýs gerek? Bu ýönekeý. Indi bu interfeýsi durmuşa geçirjek birnäçe synp döredip bileris:
public class HybridFillStrategy implements FillStrategy {

   @Override
   public void fill() {
       System.out.println("Заправляем бензином or электричеством на выбор!");
   }
}

public class F1PitstopStrategy implements FillStrategy {

   @Override
   public void fill() {
       System.out.println("Заправляем бензин только после всех остальных procedures пит-стопа!");
   }
}

public class StandartFillStrategy implements FillStrategy {
   @Override
   public void fill() {
       System.out.println("Просто заправляем бензин!");
   }
}
Üç sany hereket strategiýasyny döretdik - adaty awtoulaglar, gibridler we Formula 1 awtoulaglary üçin. Her strategiýa aýratyn ýangyç guýmak algoritmini durmuşa geçirýär. Biziň ýagdaýymyzda, bu diňe konsola çykýar, ýöne usulyň içinde käbir çylşyrymly logika bolup biler. Indiki bilen näme etmeli?
public class Auto {

   FillStrategy fillStrategy;

   public void fill() {
       fillStrategy.fill();
   }

   public void gas() {
       System.out.println("Едем вперед");
   }

   public void stop() {
       System.out.println("Тормозим!");
   }

}
FillStrategyInterfeýsimizi ene synpda meýdan hökmünde ulanýarys Auto. Üns beriň: belli bir ýerine ýetirişi kesgitlemeýäris, gaýtam interfeýsi ulanýarys. FillStrategyÇaga awtoulag sapaklarynda interfeýsiň aýratyn ýerine ýetirilmegi zerur bolar :
public class F1Car extends Auto {

   public F1Car() {
       this.fillStrategy = new F1PitstopStrategy();
   }
}

public class HybridAuto extends Auto {

   public HybridAuto() {
       this.fillStrategy = new HybridFillStrategy();
   }
}

public class Sedan extends Auto {

   public Sedan() {
       this.fillStrategy = new StandartFillStrategy();
   }
}
Näme alanymyzy göreliň:
public class Main {

   public static void main(String[] args) {

       Auto sedan = new Sedan();
       Auto hybrid = new HybridAuto();
       Auto f1car = new F1Car();

       sedan.fill();
       hybrid.fill();
       f1car.fill();
   }
}
Konsol çykyşy:

Просто заправляем бензин!
Заправляем бензином or электричеством на выбор!
Заправляем бензин только после всех остальных procedures пит-стопа!
Ajaýyp, ýangyç guýmak prosesi bolmalysy ýaly işleýär! Theeri gelende aýtsak, strategiýany konstruktorda parametr hökmünde ulanmaga hiç zat päsgel bermeýär! Mysal üçin, şuňa meňzeş:
public class Auto {

   private FillStrategy fillStrategy;

   public Auto(FillStrategy fillStrategy) {
       this.fillStrategy = fillStrategy;
   }

   public void fill() {
       this.fillStrategy.fill();
   }

   public void gas() {
       System.out.println("Едем вперед");
   }

   public void stop() {
       System.out.println("Тормозим!");
   }
}

public class Sedan extends Auto {

   public Sedan() {
       super(new StandartFillStrategy());
   }
}



public class HybridAuto extends Auto {

   public HybridAuto() {
       super(new HybridFillStrategy());
   }
}

public class F1Car extends Auto {

   public F1Car() {
       super(new F1PitstopStrategy());
   }
}
Usulymyzy işledeliň main()(üýtgewsiz galýar) we şol bir netijäni alalyň! Konsol çykyşy:

Просто заправляем бензин!
Заправляем бензином or электричеством на выбор!
Заправляем бензин только после всех остальных procedures пит-стопа!
Strategiýa nagşy algoritmler maşgalasyny kesgitleýär, olaryň hersini gurşap alýar we olaryň çalşylmagyny üpjün edýär. Müşderi tarapynda ulanylyşyna garamazdan algoritmleri üýtgetmäge mümkinçilik berýär (bu kesgitleme "Dizaýn nagyşlaryny öwrenmek" kitabyndan alyndy we maňa gaty üstünlikli görünýär). “Strategiýa” dizaýn nusgasy - 4Bizi gyzyklandyrýan algoritmler maşgalasyny (ýangyç guýýan awtoulaglaryň görnüşleri) birnäçe ýerine ýetiriş bilen aýratyn interfeýslere böldük. Olary awtoulagyň düýp manysyndan aýyrdyk. Şol sebäpden, şu ýa-da ýangyç guýmak prosesine haýsydyr bir üýtgeşme girizmeli bolsak, bu awtoulag synplarymyza hiç hili täsir etmez. Çalyşmak barada aýdylanda bolsa, oňa ýetmek üçin synpymyza diňe bir sazlaýjy usuly goşmaly Auto:
public class Auto {

   FillStrategy fillStrategy;

   public void fill() {
       fillStrategy.fill();
   }

   public void gas() {
       System.out.println("Едем вперед");
   }

   public void stop() {
       System.out.println("Тормозим!");
   }

   public void setFillStrategy(FillStrategy fillStrategy) {
       this.fillStrategy = fillStrategy;
   }
}
Indi uçuş strategiýalaryny üýtgedip bileris:
public class Main {

   public static void main(String[] args) {

       ChildrenBuggies buggies = new ChildrenBuggies();
       buggies.setFillStrategy(new StandartFillStrategy());

       buggies.fill();
   }
}
Birden çagalaryň bugdaý awtoulaglary benzin bilen doldurylyp başlasa, programmamyz şeýle ssenariýa taýyn bolar :) Bularyň hemmesi aslynda! Başga bir dizaýn nusgasyny öwrendiňiz, bu size şübhesiz zerur bolar we hakyky taslamalarda işläniňizde size birnäçe gezek kömek eder :) againene görüşeris!
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION