Cvičenie 3
Dneska si ukážeme jednu veľmi výhodnú vlastnosť OOP: observer pattern. Jedná sa o prvý z návrhových vzorov, ktoré budeme preberať.
Keď ste chceli v C sledovať zmenu nejakej hodnoty, museli ste sa stále dopytovať na zmenu (a keď ste ju sledovali z viacerých miest, tieto dopyty zbytočne stáli výpočtový výkon). Čo keby sme sa na to pozreli z druhej strany: chcem vedieť o zmene nejakej hodnoty, tak sa prihlásim na "odber noviniek" a keď k nejakej zmene dojde, budem o tom oboznámený.
3.1 Let there be light
Vytvorte si triedu Crystal
- táto bude reprezentovať svietiaci kryštál (a rozširuje AbstractActor
). V konštruktore si pripravte 2 animácie: crystal_on.png
, crystal_off.png
Pridajte metódu Toggle()
a implementujte ju nasledovne:
- nech sa pri jej zavolaní zmení stav kryštálu medzi zapnutým a vypnutým
- pri zmene stavu zmeňte animáciu
Vytvorte si triedu PowerSource - táto bude predstavovať zdroj energie (znovu rozširuje AbstractActor
).
Obdobne pridajte dve animácie source_on.png
a source_off.png
Znovu pridajte metódu Toggle()
s prakticky rovnakou implementáciou ako v prípade Crystal
Už tu môžete vidieť že máme dve (zatiaľ) prakticky rovnaké triedy, ktoré sa líšia iba v názve a animáciách - princíp DRY (don't repeat yourself) nám hovorí, že by sme tieto veci mali dať dokopy - C# však neumožňuje dediť z viacerých tried súčasne (aj keď nové verzie C# prišli s tzv. default interface methods - interface môže za určitých podmienok implementovať nejakú funkcionalitu), tak to zatiaľ necháme napokoji.
Vytvorte si však rozhranie
public interface ISwitchable
{
void Toggle();
void TurnOn();
void TurnOff();
bool IsOn();
}
Nech obidve triedy implementujú toto rozhranie, syntax je nasledovná:
public Crystal : AbstractActor, ISwitchable
{
//magic happens here
3.2 I see you
Na samotný observer pattern budeme potrebovať niekoľko rozhraní:
public interface IObserver
{
void Notify();
}
public interface IObservable
{
void Subscribe(IObserver observer);
}
Nech:
-
Crystal
implementujeIObserver
-
PowerSource
implementujeIObservable
- V
PowerSource
si držte referenciu naCrystal
- keď sa zmení stavPowerSource
dajte o tom kryštálu vedieť
3.3 My command is your wish
Písať kód, ale nič nevidieť nie je veľmi praktické - takže kus predbehneme cvičenia, o vstupoch z klávesnice a Singleton vzore sa budeme baviť nabudúce. Na zatiaľ si skopírujte do PowerSource.Update()
nasledujúcu podmienku:
if (Input.GetInstance().IsKeyPressed(Input.Key.E))
ak táto podmienka bude platiť, zavolajte Toggle
3.4 Power! Unlimited Power!
Momentálne dokážeme napájať jeden kryštál, čo je síce super, ale pravdepodobne až taký odber nemá, že by sme nevedeli pripojiť aj druhý. V C ste používali polia (array), má ich aj C# ale oveľa praktickejšie je použiť nejakú triedu, ktorá nám už funkcionalitu polí zaobaľuje. C# má takýchto tried celú sadu a sú implementované v System.Collections
namespace. Dneska budeme používať List<T>
.
Kde T
predstavuje tzv. typový parameter - používa sa, keď vopred nevieme, akého typu bude parameter na vstupe, ale už potrebujeme implementovať funkcionalitu.
List<int> list; //list of integer values
List<Crystal> crystals; //list of objects of type Crystal
...
List<string> listOfStrings = new List<string>(); //create a new instance
...
- Pridajte do
IObservable
metóduvoid Unsubscribe(IObserver observer)
- Upravte
PowerSource
tak, aby bolo možné pridávať a odoberať Observerov- na pridanie použite
List.Add(T value)
- na odobratie môžete použiť
List.Remove(T value)
- pravdepodobne budete musieť skontrolovať, či daný prvok už v zozname je - ako na to, pozrite si dostupné metódy pomocou dopĺňania kódu (ctrl+spacebar) - V rámci
TurnOn() / TurnOff()
upozornite všetky kryštály o zmene stavu zdroja elektriky
- na pridanie použite
Syntax pre forach
cyklus je:
foreach (string s in listOfStrings)
{
Console.WriteLine(s);
}