460 likes | 723 Views
Observer. (Behavioral). Observer. Apibrėžia vienas-su-daug priklausomybę tarp objektų taip, kad kuomet pasikeičia vieno objekto būsena, visiems susijusiems su juo objektams yra pranešama apie tai ir jie automatiškai atnaujinami.
E N D
Observer (Behavioral)
Observer • Apibrėžia vienas-su-daug priklausomybę tarp objektų taip, kad kuomet pasikeičia vieno objekto būsena, visiems susijusiems su juo objektams yra pranešama apie tai ir jie automatiškai atnaujinami. • Define a one-to-many dependency between objects so that when oneobject changesstate, all its dependents are notified and updatedautomatically.
Motyvacija • OO programavimas yra apie objektus ir jų bendradarbiavimą. • Dažnai pasitaiko atvejai, kuomet kai kurie objektai turi būti informuojami apie pasikeitimus kituose objektuose. • Geras projektavimas – atskirti kiek įmanoma ir sumažinti priklausomybes. • Šablonas gali būti naudojamas visada, kuomet subject turi būti stebimas vieno ar daugiau stebėtojų (observers)
Struktūra • Observable (subject) – interfeisas ar abstrakti klasė, apibrėžianti operacijas, skirtas stebėtojų (observers) prijungimui ir atjungimui. • ConcreteObservable – konkreti Observable klasė. Joje laikoma objekto būsena ir kuomet įvyksta būsenos pasikeitimas, ji praneša apie tai prijungtiems stebėtojams (Observers). • Observer – interfeisas ar abstrakti klasė, apibrėžianti operacijas, skirtas informuoti apie būseną. • ConcreteObserver – reali Observer realizacija. • Observable.notify() – metodas informuoja kiekvieną stebėtoją, iškviesdamas Observer.update() metodą.
Elgsena • Kliento klasė sukuria ConcreteObservable objektą. • Tuomet sukuria ir prijungia prie ConcreteObservable konkrečius stebėtojus, naudojant metodus, apibrėžtus Observable interfeise. • Kiekviena kartą, kai keičiasi subject būsena, jis informuoja prijungtus Observers, pagal metodus, apibrėžtus Observer interfeise. • Kuomet pridedamas naujas Observer, mums tereikia jį instantijuoti kliento klasėje ir pridėti jį prie Observable objekto. • Klasės, kurios yra jau sukurtos, liks nepasikeitę.
Bendradarbiavimas • ConcreteObservable informuoja savo stebėtojus, kuomet įvyksta pasikeitimas, kuris padaro stebėtojo būseną nesuderinamą su jo paties. • ConcreteObserver gali užklausti subject‘o informacijos, po informavimo apie pasikeitimus. • Šią informaciją ConcreteObserver naudoja suderinti savo būseną su subject būsena. • Observer objektas, kuris inicijuoja pasikeitimus, atideda savo atnaujinimą, kol gauna pranešimą iš subject. • Notify ne visada yra iškviečiamas iš stebėtojo. • Gali būti iškviečiamas iš bet kokio kito objekto.
Kada naudoti Observer? • Kuomet būsenos pasikeitimas viename objekte turi būti atspindėtas kitame objekte be glaudaus objektų susiejimo (tight coupling). • Kuomet kuriama sistema ateityje turės būti praplėsta naujais stebėtojais, tai įgyvendinant minimaliais pokyčiais.
Pasekmės (+) • Abstraktus Observable ir Observer susiejimas. • Viskas, ką žino subject yra tai, kad jis turi sąrašą stebėtojų, kur kiekvienas atitinka Observer klasės interfeisą. • Subject nežino konkrečios stebėtojo klasės, tokiu būdu susiejimas yra abstraktus ir minimalus. • Paskleisto bendradarbiavimo palaikymas (Support for broadcast communication). • Kitaip nei paprastoj užklausoj, pranešime apie pasikeitimus, kurį siunčia subject, neturi būti nurodytas jo gavėjas. • Pranešimas automatiškai perduodamas visiems susijusiems objektams. • Siuntėjas neturi rūpintis, kiek yra susijusių objektų, jo vienintelė atsakomybė – informuoti stebėtojus. • Tai suteikia laisvę bet kada pašalinti ar pridėti stebėtojus. • Nuo stebėtojo priklauso ar apdoroti, ar ignoruoti pranešimą.
Pasekmės (-) • Nenumatyti atnaujinimai. • Because observers have no knowledge of each other'spresence, they canbe blind to the ultimate cost of changing the subject. • Iš pažiūros nepavojinga operacija subject‘e, gali sukelti kaskadinius atnaujinimus stebėtojuose ir jų priklausomuose objektuose. • Gerai neapibrėžti ar palaikomi priklausomybės kriterijai paprastai veda prie „netikrų“ atnaujinimų, kuriuos gali būti sunku atsekti.
Pavyzdys. Naujienų agentūra • Naujienų agentūra renka žinias ir publikuoja jas skirtingiems abonentams. • Reikia sukurti sistemą, kuri, įvykus kokiam nors įvykiui, nedelsiant apie tai praneštų abonentams. • Abonentai gali gauti žinias skirtingais būdais: • E-paštas; • SMS, ... • Sprendimas turi būti praplečiamas, kad galėtų palaikyti naujus abonentų tipus.
Struktūra (1) • Agentūra atvaizduota Observable(Subject) klase NewsPublisher. • Abstrakti klasė, kadangi agentūrai reikia sukurti keletą Observable tipo objektų: • Pradžioje tik verslo žinioms, bet vėliau ir sporto, politikos ir t.t. žinios bus publikuojamos. • Konkreti klasė – BusinessNewsPublisher.
Struktūra (2) • Stebėtojo logika realizuota NewsPublisher‘yje (NP). • Čia laikomas visų abonentų sąrašas ir NP informuoja juos apie naujausias žinias. • Abonentai atvaizduojami keliais stebėtojais (SMSsubscriber, EmailSubscriber). • Stebėtojai yra paveldėti iš Subscriber. • Tai abstrakti klasė, kuri yra žinoma NP. • NP nežino apie konkrečius stebėtojus, žino tik jų abstrakciją. • Pagrindinėje klasėje sukuriamas leidėjas (Observable) ir keli abonentai (Observers). • Abonentai yra prijungti prie ledėjo ir gali išsiregistruoti. • Tokioje architektūroje lengva pridėti naujus abonentus (instant messaging,..) ir naujus leidėjų tipus (Weather, Sport, ..)
Realizacijos problemos (1) • Many subjects to Many observers • Gali pasitaikyti, kad bus daug stebėtojų, kurie stebės daugiau nei vieną subject‘ą. • Tokiu atveju stebėtojas turi būti informuojamas ne tik apie pokyčius, bet ir apie tai, kurio subject‘o būsena pasikeitė. • Tai gali būti realizuota pridedant nuorodą į save patį (this) update() metode.
Realizacijos problemos (2) • Who triggers the update? • Bendravimas tarp subject‘o ir jo stebėtojų yra vykdomas per notify() metodą. • Paprastai šis metodas yra paleidžiamas iš subject‘o, kuomet pasikeičia jo būsena. • Tačiau kartais, kuomet atnaujinimai yra dažni, nuoseklūs pasikeitimai subject‘e iššauks daug nereikalingų atnaujinimo operacijų stebėtojuose. • Kad procesas taptų efektyvesnis, stebėtojas gali būti atsakingas už informavimo operacijos pradėjimą, kuomet ji yra reikalinga.
Realizacijos problemos (3) • Making sure Subject state is self-consistent before notification. • Svarbu įsitikinti, kad Subject būsena yra nuosekli (self-consistent), prieš iškviečiant Notify() metodą. • Jei subject‘o būsenos pakeitimai atliekami po stebėtojo informavimo, stebėtojas atsinaujins su sena būsena.
Pavyzdys Stebėtojas informuojamas, kuomet subject‘o būsena nenuosekli
Push ir Pull bendravimo metodai • Push model – subject siunčia stebėtojui detalią informaciją apie pasikeitimą, nesvarbu ar stebėtojas ją naudos ar ne. • Tai neefektyvu, kuomet siunčiame didelius kiekius informacijos, kurios nenaudosime. • Galima siųsti tik tą informaciją, kurios reikalauja stebėtojas. • Tokiu atveju subject‘as turėtų galėti atskirti skirtingus stebėtojų tipus ir žinoti, kokie duomenys reikalingi kiekvienam iš jų (subject layer is more coupled to observer layer).
Push ir Pull bendravimo metodai • Pull model – subject‘as tik informuoja stebėtojus, kuomet jo būsena pasikeičia, o toliau kiekvieno stebėtojo atsakomybė, ištraukti (pull) reikalingus duomenis iš subject‘o. • Tai gali būti neefektyvu, kadangi bendravimas vykdomas dviem žingsniais ir gali iškilti problemos multithreading aplinkose.
Efektyvumo padidinimas • Efektyvumas gali būti padidintas nurodant, kokiais įvykiais „domisi“ kiekvienas stebėtojas. • Tai gali būti realizuojama pridedant naują klasę, apibrėžiančią aspektus. • Kuomet stebėtojas priregistruojamas, jis aprūpins aspektais, kuriais jis domisi.
Flyweight (Structural)
Flyweight • The intent of this pattern is to use sharing to support a large number of objects that have part of their internal state in common where the other part of state can vary. • Flyweight yra objektas, kuris minimizuoja atminties naudojimą, dalindamasis kiek įmanoma daugiau duomenų su kitais panašiais objektais. Flyweight: • lengviausiojo svorio boksininkas/imtynininkas/sunkumų kilnotojas • tech.svorelis
Motyvacija • Kai kuriose programose būna daug objektų, kurie turi bendrą būsenos dalį. • Pavyzdžiui, karo žaidime yra didelis kiekis kareivių objektų: • Kareivio objektas turi grafinį kareivio atvaizdavimą; • Kareivio elgseną (pvz. judėjimas); • Šaunamieji ginklai; • Gyvybę (health); • Padėtį karo teritiorijoje.
Motyvacija • Privalome kurti daug kareivių objektų, tačiau jie sunaudos labai daug atminties. • Kareivio atvaizdavimas ir elgsena visiems objektams yra tokie patys, tačiau gyvybė ir padėtis skiriasi.
Dalyviai • Flyweight – interfeisas, per kurį flyweight‘ai gauna išorinę (extrinsic) būseną. • ConcreteFlyweight - realizuoja Flyweightinterfeisą ir saugo vidinę (intrinsic) būseną. • Šis objektas turi būti bendrinamas (sharable); • Bet kokia jo saugojama būsena privalo būti vidinė – nepriklausoma nuo ConcreteFlyweight objekto konteksto. • UnsharedConcreteFlyweight: • ne visos Flyweightsubklasės turi būti bendrinamos (shared). • Flyweightinterfeisasįgalina bendrinimą, tačiau jo neprimeta. • Dažnai pasitaiko, kadkai kuriuose lygmenyse UnsharedConcreteFlyweight objektai turi ConcreteFlyweight objektus kaip savo „vaikus“.
Dalyviai • FlyweightFactory: • Kuria ir valdo flyweight objektus; • Užtikrina, kad flyweight‘ai yra tinkamai bendrinami. Kuomet klientas prašo flyweight‘o, FlyweightFactory objektas pateikia egzistuojantį arba sukuria naują. • Client: • Laikonuorodasį flyweight‘us; • Apskaičiuoja arba laiko išorinę flyweight‘ų būseną.
Objektų diagrama Diagrama parodo, kaip flyweight‘ai yra bendrinami
Kada naudoti Flyweight šabloną? • Šablono efektyvumas stipriai priklauso nuo to, kaip ir kur jis naudojamas. • Šablonas turi būti naudojamas, jei tenkinami visi išvardinti teiginiai: • Taikomoji programa naudoja didelį kiekį objektų; • Daugelio objektų būseną galima paversti išorine (extrinsic). • Daugelis objektų grupių gali būti pakeistos santykiniai mažu kiekiu bendrinamų objektų, kuomet išorinė būsena yra pašalinama. • Taikomoji programa nepriklauso nuo objektų identiškumo. • Kadangi flyweight objektai gali būti bendrinami, identiškumo testai gražins TRUE, net ir konceptualiai skirtingiems objektams
Pasekmės • Šablonas taupo atmintį, dalindamasis flyweight objektais tarp klientų. • Sutaupomos atminties kiekis paprastai priklauso nuo flyweight kategorijų kiekio.
Pavyzdys Supaprastinta klasių diagrama Kintama būsena Bendra būsena
Pavyzdys. Karo žaidimas • Pavyzdys iliustruoja 5 Soldier klientus, kur kiekvienas klientas laiko savo vidinę būseną, kuri yra išorinė flyweight kareiviui. • Nors sukurti 5 klientai, tik vienas flyweight Soldier bus naudojamas.
Pavyzdys. Realizacija Soldier interfeisas (flyweight interfeisas)
Pavyzdys. Realizacija SoldierImp, realizuojantis flyweight
Pavyzdys. Realizacija Soldierfactory, iš kurio sukuriam Soldier Flyweight
Pavyzdys. Realizacija SoldierClient realizacija. Klientas naudoja Flyweight soldier nuorodą, kad atliktų savo užduotis
Pavyzdys. Realizacija SC SC SC SC SC SoldImp :Soldier nuoroda