Strategiya sxemasi - Strategy pattern

Yilda kompyuter dasturlash, strategiya namunasi (shuningdek,. nomi bilan ham tanilgan siyosat namunasi) a xulq-atvori dasturiy ta'minot dizayni ni tanlashga imkon beradi algoritm ish vaqtida. To'g'ridan-to'g'ri bitta algoritmni amalga oshirish o'rniga, kod algoritmlar oilasida ishlatilishi kerak bo'lgan ko'rsatmalar oladi.[1]

Strategiya algoritmni uni ishlatadigan mijozlardan mustaqil ravishda farq qilishga imkon beradi.[2] Strategiya nufuzli kitobga kiritilgan naqshlardan biridir Dizayn naqshlari Gamma va boshq.[3] moslashuvchan va qayta ishlatiladigan ob'ektga yo'naltirilgan dasturiy ta'minotni loyihalashtirishni tavsiflash uchun dizayn naqshlaridan foydalanish kontseptsiyasini ommalashtirdi. Ishlash vaqtigacha qaysi algoritmdan foydalanish to'g'risida qarorni qoldirish qo'ng'iroq kodini yanada moslashuvchan va qayta ishlatishga imkon beradi.

Masalan, kirish ma'lumotlarini tekshirishni amalga oshiradigan sinf, ma'lumotlar turiga, ma'lumotlar manbasiga, foydalanuvchi tanloviga yoki boshqa kamsituvchi omillarga qarab tasdiqlash algoritmini tanlash uchun strategiya sxemasidan foydalanishi mumkin. Ushbu omillar ish vaqtigacha ma'lum emas va ular tubdan boshqacha tekshirishni talab qilishi mumkin. Tasdiqlash ob'ektidan alohida kiritilgan tasdiqlash algoritmlari (strategiyalari) tizimning turli sohalarida (yoki hatto turli xil tizimlarda) boshqa tasdiqlovchi ob'ektlar tomonidan ishlatilishi mumkin kodni takrorlash.

Odatda, strategiya namunasi ma'lumotlar tarkibidagi ba'zi bir kodlarga havolani saqlaydi va uni qaytarib oladi. Bunga mahalliy kabi mexanizmlar orqali erishish mumkin funktsiya ko'rsatgichi, birinchi darajali funktsiya, sinflar yoki sinf misollari ob'ektga yo'naltirilgan dasturlash tillar yoki tilni amalga oshirishda kodni ichki xotirasiga kirish aks ettirish.

Tuzilishi

UML klassi va ketma-ketlik diagrammasi

Strategiyani ishlab chiqish namunasi uchun namunaviy UML klassi va ketma-ketlik diagrammasi. [4]

Yuqorida UML sinf diagrammasi, Kontekst sinf to'g'ridan-to'g'ri algoritmni amalga oshirmaydi. Kontekst ga ishora qiladi Strategiya algoritmni bajarish interfeysi (strategiya.algoritmi ()) qiladi Kontekst algoritm qanday amalga oshirilishidan mustaqil Strategiya1 va Strategiya2 sinflar Strategiya interfeysi, ya'ni algoritmni amalga oshiradi (kapsulalash).
The UML ketma-ketlik diagrammasi ish vaqtidagi o'zaro ta'sirlarni ko'rsatadi: The Kontekst ob'ekt algoritmni boshqasiga topshiradi Strategiya ob'ektlar. Birinchidan, Kontekst qo'ng'iroqlar algoritm () a Strategiya1 algoritmni bajaradigan va natijani qaytaradigan ob'ekt Kontekst. Keyinchalik, Kontekst strategiyasini o'zgartiradi va chaqiradi algoritm () a Strategiya2 algoritmni bajaradigan va natijani qaytaradigan ob'ekt Kontekst.

Sinf diagrammasi

Strategiya namunasi UML

[5]

Strategiya sxemasi LePUS3 (afsona )

Misol

C #

Quyidagi misol C #.

jamoat sinf StrategyPatternWiki{    jamoat statik bekor Asosiy(Ip[] kamon)    {        // Strategiyalar tayyorlang        var normalStrategy    = yangi NormalStrategy();        var happyHourStrategy = yangi HappyHourStrategy();        var firstCustomer = yangi CustomerBill(normalStrategy);        // Oddiy hisob-kitob        firstCustomer.Qo'shish(1.0, 1);        // Baxtli soatni boshlang        firstCustomer.Strategiya = happyHourStrategy;        firstCustomer.Qo'shish(1.0, 2);        // Yangi mijoz        CustomerBill secondCustomer = yangi CustomerBill(happyHourStrategy);        secondCustomer.Qo'shish(0.8, 1);        // Mijoz to'laydi        firstCustomer.Chop etish();        // Baxtli soatni tugating        secondCustomer.Strategiya = normal strategiya;        secondCustomer.Qo'shish(1.3, 2);        secondCustomer.Qo'shish(2.5, 1);        secondCustomer.Chop etish();    }}// CustomerBill sinf nomi sifatida, chunki u mijozning hisobiga tor doirada kiradisinf CustomerBill{    xususiy Ilist<ikki baravar> ichimliklar;    // Get / Set Strategy    jamoat IBillingStrategy Strategiya { olish; o'rnatilgan; }    jamoat CustomerBill(IBillingStrategy strategiya)    {        bu.ichimliklar = yangi Ro'yxat<ikki baravar>();        bu.Strategiya = strategiya;    }    jamoat bekor Qo'shish(ikki baravar narx, int miqdor)    {        bu.ichimliklar.Qo'shish(bu.Strategiya.GetActPrice(narx * miqdor));    }    // Xarajatlarni to'lash    jamoat bekor Chop etish()    {        ikki baravar sum = 0;        har biriga (var drinkCost yilda bu.ichimliklar)        {            sum += drinkCost;        }        Konsol.WriteLine($"To'lov muddati: {sum}.");        bu.ichimliklar.Aniq();    }}interfeys IBillingStrategy{    ikki baravar GetActPrice(ikki baravar xom narx);}// Oddiy hisob-kitob strategiyasi (o'zgarishsiz narx)sinf NormalStrategy : IBillingStrategy{    jamoat ikki baravar GetActPrice(ikki baravar xom narx) => xom narx;}// Baxtli soat strategiyasi (50% chegirma)sinf HappyHourStrategy : IBillingStrategy{    jamoat ikki baravar GetActPrice(ikki baravar xom narx) => xom narx * 0.5;}

Java

Quyidagi misol Java.

Import java.util.ArrayList;interfeys BillingStrategy {    // Yuzlab yuruvchi nuqsonni oldini olish uchun narxni tsent bilan ishlating    int getActPrice(int xom narx);      // Oddiy hisob-kitob strategiyasi (o'zgarishsiz narx)    statik BillingStrategy normalStrategy() {        qaytish xom narx -> xom narx;    }      // Baxtli soat strategiyasi (50% chegirma)    statik BillingStrategy happyHourStrategy() {        qaytish xom narx -> xom narx / 2;    }}sinf CustomerBill {    xususiy final Ro'yxat<Butun son> ichimliklar = yangi ArrayList<>();    xususiy BillingStrategy strategiya;    jamoat CustomerBill(BillingStrategy strategiya) {        bu.strategiya = strategiya;    }    jamoat bekor qo'shish(int narx, int miqdor) {        bu.ichimliklar.qo'shish(bu.strategiya.getActPrice(narx*miqdor));    }    // Xarajatlarni to'lash    jamoat bekor chop etish() {        int sum = bu.ichimliklar.oqim().mapToInt(v -> v).sum();        Tizim.chiqib.println("Jami muddati:" + sum);        bu.ichimliklar.aniq();    }    // Strategiyani o'rnating    jamoat bekor setStrategy(BillingStrategy strategiya) {        bu.strategiya = strategiya;    }}jamoat sinf StrategyPattern {    jamoat statik bekor asosiy(Ip[] dalillar) {        // Strategiyalar tayyorlang        BillingStrategy normal strategiya    = BillingStrategy.normalStrategy();        BillingStrategy happyHourStrategy = BillingStrategy.happyHourStrategy();        CustomerBill firstCustomer = yangi CustomerBill(normalStrategy);        // Oddiy hisob-kitob        firstCustomer.qo'shish(100, 1);        // Baxtli soatni boshlang        firstCustomer.setStrategy(happyHourStrategy);        firstCustomer.qo'shish(100, 2);        // Yangi mijoz        CustomerBill secondCustomer = yangi CustomerBill(happyHourStrategy);        secondCustomer.qo'shish(80, 1);        // Mijoz to'laydi        firstCustomer.chop etish();        // Baxtli soatni tugating        secondCustomer.setStrategy(normalStrategy);        secondCustomer.qo'shish(130, 2);        secondCustomer.qo'shish(250, 1);        secondCustomer.chop etish();    }}

Strategiya va ochiq / yopiq printsip

Tezlashtirish va tormoz xatti-harakatlar har bir yangi versiyada e'lon qilinishi kerak avtomobil modeli.

Strategiya sxemasiga ko'ra, sinfning xatti-harakatlari meros bo'lib o'tmasligi kerak. Buning o'rniga ular interfeyslardan foydalanib kapsüllenmelidir. Bu mos keladi ochiq / yopiq printsip (OCP), bu sinflarni kengaytirish uchun ochiq bo'lishi kerak, ammo o'zgartirish uchun yopiq bo'lishi kerak.

Masalan, avtoulov sinfini ko'rib chiqing. Avtomobil uchun ikkita mumkin bo'lgan funktsiyalar mavjud tormoz va tezlashtirmoq. Modellar orasida tezlashish va tormoz harakati tez-tez o'zgarib turishi sababli, odatdagi yondashuv bu xatti-harakatlarni subklasslarda amalga oshirishdir. Ushbu yondashuv muhim kamchiliklarga ega: avtoulovning har bir yangi modelida tezlashtirish va tormoz harakati e'lon qilinishi kerak. Ushbu xatti-harakatlarni boshqarish ishi modellar sonining ko'payishi bilan juda ko'payadi va kodlarni modellar bo'yicha takrorlashni talab qiladi. Bundan tashqari, har bir modeldagi kodni o'rganmasdan har bir model uchun xatti-harakatning aniq xususiyatini aniqlash oson emas.

Strategiya sxemasidan foydalaniladi meros o'rniga kompozitsiya. Strategiya uslubida xatti-harakatlar alohida interfeyslar va ushbu interfeyslarni amalga oshiradigan maxsus sinflar sifatida tavsiflanadi. Bu xatti-harakatlar va xulq-atvorni ishlatadigan sinf o'rtasida yaxshi ajralish imkonini beradi. Xulq-atvorni ishlatadigan sinflarni buzmasdan o'zgartirish mumkin va sinflar hech qanday kodni sezilarli darajada o'zgartirishni talab qilmasdan ishlatiladigan maxsus dasturni o'zgartirish orqali xatti-harakatlar o'rtasida almashinishi mumkin. Xulq-atvorni ish vaqtida ham, dizayn vaqtida ham o'zgartirish mumkin. Masalan, avtoulov ob'ektining tormoz harakati o'zgarishi mumkin BrakeWithABS () ga Tormoz () ni o'zgartirib tormoz Xatti-harakatlar a'zo:

tormoz Xatti-harakatlar = yangi Tormoz();
/ * Algoritmlarning kapsulalangan oilasi * Interfeys va uni amalga oshirish */jamoat interfeys IBrakeBeavior {    jamoat bekor tormoz();}jamoat sinf BrakeWithABS asboblar IBrakeBeavior {    jamoat bekor tormoz() {        Tizim.chiqib.println("ABS bosilgan tormoz");    }}jamoat sinf Tormoz asboblar IBrakeBeavior {    jamoat bekor tormoz() {        Tizim.chiqib.println("Oddiy tormoz bosildi");    }}/ * Yuqoridagi algoritmlarni bir-birining o'rnida ishlata oladigan mijoz * /jamoat mavhum sinf Avtomobil {    xususiy IBrakeBeavior tormoz Xatti-harakatlar;    jamoat Avtomobil(IBrakeBehavior tormoz Xatti-harakatlar) {      bu.tormoz Xatti-harakatlar = tormoz Xatti-harakatlar;    }    jamoat bekor Tormoz() {        tormoz Xatti-harakatlar.tormoz();    }    jamoat bekor setBrakeBehavior(IBrakeBeavior brakeType) {        bu.tormoz Xatti-harakatlar = brakeType;    }}/ * Mijoz 1 konstruktorda bitta algoritmni (Tormoz) ishlatadi * /jamoat sinf Sedan uzaytiradi Avtomobil {    jamoat Sedan() {        super(yangi Tormoz());    }}/ * Client 2 konstruktorida boshqa algoritmni (BrakeWithABS) ishlatadi * /jamoat sinf SUV uzaytiradi Avtomobil {    jamoat SUV() {        super(yangi BrakeWithABS());    }}/ * Avtomobil misolidan foydalanish * /jamoat sinf CarExample {    jamoat statik bekor asosiy(final Ip[] dalillar) {        Avtomobil sedanAvtomobil = yangi Sedan();        sedanAvtomobil.Tormoz();  // Bu "tormoz" sinfini chaqiradi        Avtomobil suv mashinasi = yangi SUV();        suv mashinasi.Tormoz();    // Bu "BrakeWithABS" sinfini chaqiradi        // tormoz harakatini dinamik ravishda o'rnating        suv mashinasi.setBrakeBehavior( yangi Tormoz() );        suv mashinasi.Tormoz();    // Bu "tormoz" sinfini chaqiradi    }}

Shuningdek qarang

Adabiyotlar

  1. ^ "Strategiyani ishlab chiqish namunasi - muammo, echim va qo'llanilishi". w3sDesign.com. Olingan 2017-08-12.
  2. ^ Erik Freeman, Elisabet Freeman, Keti Sierra va Bert Bates, Birinchi dizayn naqshlarini boshlang, Birinchi nashr, 1-bob, 24-bet, O'Reilly Media, Inc, 2004 y. ISBN  978-0-596-00712-6
  3. ^ Erix Gamma, Richard Xelm, Ralf Jonson, Jon Vlissidlar (1994). Dizayn naqshlari: Qayta foydalaniladigan ob'ektga yo'naltirilgan dasturiy ta'minot elementlari. Addison Uesli. pp.315ff. ISBN  0-201-63361-2.CS1 maint: bir nechta ism: mualliflar ro'yxati (havola)
  4. ^ "Strategiyani ishlab chiqish namunasi - Tuzilma va hamkorlik". w3sDesign.com. Olingan 2017-08-12.
  5. ^ http://www.mcdonaldland.info/2007/11/28/40/

Tashqi havolalar