Wpis z mikrobloga

Siema mirki,
Piszę program w C# mam wykorzystać 5 wzorców projektowych i trochę je upycham na siłę. Ale nie o tym rzecz, wykorzystałem wzorzec fabryki do tworzenia obiektów. Jednak natrafiłem na problem wydaje mi się błachy.
Najlepiej na to odpowie chyba kod:

Event cos = eventFactory.getEvent("Urodziny");
"Event" jest klasą abstrakcyjną a tworzy się tu obiekt klasy "EventBirthday" zawiarający nowe pole "osoba" i jak teraz mając obiekt "cos" zeedytować to pole jeżeli nie mam do niego dostępu z racji że nie występuje w klasie "Event"?

#programowanie #cszarp
  • 15
@czupek: Tak właśnie operuję na obiekcie typu Event. Hmm za każdym razem jak będę chciał zmienić pole osoba operując na Event będę musiał rzutować?

Czyli używać kodu w tym stylu? (chyba że jest jakieś ładniejsze rozwiązanie to bardzo bym prosił o przykład):

if(cos is EventBirthday)
{
EventBirthday tmp = new EventBirthday();
tmp = (EventBirthday)cos;
tmp.Person = "Adrian";
cos = tmp;
}
@nekrofil: Nie musisz tworzyć new EventBirthday.

if(cos is EventBirthday){
var inneCoś = cos as EventBirthday;
inneCoś.Person = "Adrian"
}

ale już z inneCoś to już nowy obiekt, nowego typu.
cos pozostanie obiektem Event, bez pola Person.
@nekrofil: > Tak właśnie operuję na obiekcie typu Event. Hmm za każdym razem jak będę chciał zmienić pole osoba operując na Event będę musiał rzutować?

No tak. Masz fabrykę obiektów typu Event, które mają swoje pola. W obiekcie dziedziczącym (czy tam impelementującym klasę abstrakcyją) masz tylko i wyłącznie to co było w tej klasie. Podobnie jest z interfejsami. O

Osobiście rzadko korzystam z klas abstrakcyjnych, więc mogę coś popierzyć.
@czupek: Hmm oki dzięki wielkie!
Jednak jeżeli później mam w kodzie:

Console.WriteLine(cos.ToString());
To wyświetla elegancko pole Person. Wiem jak to działa że kompilator wie jaką metodę użyć (że z klasy EventBirthday) Ale rozumiem że jako tako ustawiania zmiennej w jakiś podobny ładny sposób już nie można robić ?
@nekrofil: A to ciekawe. A jak zrobisz w obiekcie EventBirthday override na toString(), i dasz tam tylko wypisanie Person, a w Event zostawisz po staremu, to co wyswietli Console.WriteLine(cos.ToString()) ?
@nekrofil: Castowanie z klasy dziedziczonej na dziedziczącą jest imo błędem, bo nie ma niczego, co zagwarantuje Ci, że castujesz do właściwego typu. Może to skutkować ( z tego co pamiętam, ja niezbyt into .NET ) rzuceniem wyjątku przez maszynę wirtualną, czegoś a'la ClassCastException

IMO niepotrzebnie pakujesz tutaj factory, eventy jako struktury reprezentujące wartość można jak najbardziej tworzyć z łapy, zwykłym "new", chyba, że chcesz mieć fabrykę per typ eventu ( w
@czupek: No dobrze jednak ja to akurat rozumiem i tak ma to działać ;)
@alex-fortune: Hmm przyznam się szczerze że dopiero zaczynam z wzorcami i trochę tak metodą prób i błędów je implementuję. A tu zadanie żeby władować aż 5 wzorców więc nie ukrywam że w niektórych miejscach są na siłe.

Przepatrzę twoje propozycje. Jednak ja użyłem już wzorców Factory (produkuje eventy: EventBirthday lub EventMeeting), singleton (tylko jedna instancja fabryki)
@nekrofil: Lepiej nie robić fabryki, która zwraca Ci dwa różne interfejsy, bo jak sam zauważyłeś, potem nie masz do nich dostępu. Dużo lepiej jest robić wiele fabryk, które potrafią stworzyć różne klasy, które implementują TEN SAM interfejs. Wtedy nawet jeśli masz ten sam interfejs na wyjściu, nie ma żadnego problemu.
@alex-fortune: Hmm może nie zrozumiałem Twojego rozwiązania ale wydaje mi się że właśnie to robię EventBirthday i EventMeeting dziedziczą po abstrakcyjnej Event który obiekt zwraca moja fabryka. Tylko w klasie EventBirthday jest jeszcze dodatkowe pole z którym mam duży problem żeby je zmienić operując na obiekcie typu Event.
@nekrofil: Nie możesz zmieniać dodatkowego pola, bo go tam z perspektywy klienta nie ma. Możesz przekazać wartość w konstruktorze, ale tutaj pojawia się kwestia sensu używania fabryki, bo sam podtyp nie ma sensu (przynajmniej tak to wygląda). Klasy ma różnić implementacja, a nie dane (te #!$%@? typy kaczek i psów to zbrodnia a nie nauczanie) i tak jak @alex-fortune napisał - obiekty oparte o prymitywy rzadko potrzebują fabryki.

Poza tym uważaj,
@nekrofil: Pomysl o tym z perspektywy kodu, ktory komunikuje sie z fabryka - on z powrotem dostaje Event, on nie ma pojęcia ze z tylu tam moze byc jakies event birthday czy event meeting. Jeśli potrzebujesz dostać z powrotem wyspecjalizowany typ, to robisz wyspecjalizowane fabryki, chociaż tak jak juz wspomniałem, IMO dla obiektów ktore są identyfikowane przez wartość ( potocznie Value Objects - swoją drogą to wzorzec sam w sobie )