Przeczytaj
Diagram klas
Diagram klas powinien być tworzony na podstawie diagramu pakietów lub – co najmniej – powinien być z nim kompatybilny.
Przypomnijmy, jak wyglądał diagram z poprzedniego e‑materiału i na jego podstawie spróbujmy opracować następny diagram.
![Ilustracja przedstawia trzy ikony folderów. Folder pierwszy podpisany jako: Sterowanie. Wewnątrz folderu znajduje się zielony blok o tytule ObsługaWejścia. Folder drugi podpisany jako: Zachowanie rozgrywki. Wewnątrz folderu znajdują się zielone bloki o tytułach: Owoc, Wąż, Plansza,. Folder trzeci podpisany jako: Grafika. Wewnątrz folderu znajduje się folder WyświetlanieGrafiki.](https://static.zpe.gov.pl/portal/f/res-minimized/R12TkaS9hZi0G/1662544128/Yit39Z0ammFdMvlZ7Yhjwo31pc3Y24Pe.png)
Zacznijmy od pakietu sterowania. Znajduje się w nim jedna klasa. Zastanówmy się, jakie metody powinniśmy zaimplementować.
W klasie koniecznie musi się znaleźć metoda, która będzie poprawnie przechwytywać komunikaty gracza i prawidłowo je przetwarzać. W tym miejscu musimy zwrócić uwagę, że dla Javy, C++ i Pythona wyświetlanie może działać troszeczkę inaczej. Dlatego właściwa implementacja może wymagać użycia klas charakterystycznych dla danego języka. Przy czym nasz diagram pakietów jest ogólny dla kilku języków.
W naszym przypadku postaramy się stworzyć jak najogólniejszy diagram – tak, aby nie kierować toku myślenia na jakiś konkretny język.
Dziedziczenia w językach Java, C++ i Python mają różne ograniczenia. W C++ i Pythonie dziedziczenie po dziesięciu klasach jednocześnie jest możliwe, w Javie już nie. Wynika to z tego, że języki C++ i Python umożliwiają tzw. wielodziedziczenie.
Sama klasa, w diagramie klas, będzie przybierać następującą postać:
![Ilustracja przedstawia klasę w postaci zielonego prostokąta o tytule: NazwaKlasy. Wewnątrz niego znajdują się zmienne: + ZmiennaPubliczna, -ZmiennaPrywatna, #ZmiennaChroniona, oraz z metodami: +metodaPubliczna(), -metodaPrywatna(), #metodaChroniona().](https://static.zpe.gov.pl/portal/f/res-minimized/RNUoy8xWhUB9D/1662544128/1AfNQTdGzPXjXELoE2inkx99EBfXNrqb.png)
Plus przed nazwą oznacza, że dana metoda lub zmienna jest publiczna (public), minus przed nazwą oznacza, że dana metoda lub zmienna jest prywatna (private), a hash przed zmienną lub metodą oznacza ochronę (protected).
W naszej klasie ObsługaWejścia
musimy zawrzeć metodę, która będzie odpowiednio modyfikować stan rozgrywki, w zależności od tego, co gracz wprowadzi na wejściu.
![Ilustracja przedstawia klasę w postaci zielonego prostokąta o tytule: ObsługaWejścia. Wewnątrz niej znajduje się metoda: +zinterpretujWciśniętyPrzycisk().](https://static.zpe.gov.pl/portal/f/res-minimized/RT42jz2VIrJqu/1662544129/F4jHHlQ8rWORFpdcQ4Z26PDlXYGl7LpP.png)
Klasa ta, pomimo posiadania wyłącznie jednej metody i tak będzie dość rozbudowana. Musimy w niej zawrzeć interpretację dla możliwości klikania trzech przycisków w trakcie rozgrywki. Natomiast w momencie, gdy rozgrywka jest zatrzymana, musimy również poprawnie zinterpretować to, co gracz chciał nam przekazać.
Kolejną klasą, którą stworzymy, będzie Owoc
. Klasa ta będzie posiadała przynajmniej jedną zmienną przechowującą informację, jaką liczbę punktów otrzyma gracz, jeżeli dany Owoc
zostanie zjedzony. Zawrzemy w niej również metodę sprawdzPunkty()
, ponieważ odczytywanie bezpośrednio ze zmiennej zawartej w samej klasie niesie ze sobą kilka problemów.
Po pierwsze, odczytywana jest wartość oryginalna i niezmodyfikowana, a istnieje spora szansa, że w toku tworzenia oprogramowania stwierdzimy, że potrzebne będzie wstępne przetworzenie tej wartości przed jej użyciem. Dlatego też zmienne z tej klasy będziemy odczytywać za pomocą getterów, a modyfikować za pomocą setterów. Same zmienne będą natomiast prywatne, żeby uniknąć pomyłek w trakcie pisania kodu. Ukrywanie zmiennych i metod jest określane w programowaniu obiektowym jako hermetyzacja (czyli enkapsulacja lub kapsułkowanie).
![Ilustracja przedstawia klasę w postaci zielonego prostokąta o tytule: Owoc. Posiada ona zmienne: -liczbaPunktów, oraz metody: +sprawdźPunkty(), +ustawPunkty().](https://static.zpe.gov.pl/portal/f/res-minimized/R15HdfsaiE12Y/1662544129/qDk3XxXgN7tEBka6FqWpvVnnYV5nZVwJ.png)
Klasa Wąż
będzie już bardziej rozbudowana. Potrzebujemy kilku informacji. Po pierwsze, informację o punktach będziemy przechowywać jako jego zmienną. Z racji tego, że liczba punktów determinuje długość ogona, dla oszczędności pamięci zdefiniujemy tę zmienną w klasie Wąż
. Oczywiście można taką zmienną umieścić również w innym miejscu, np. w klasie Plansza lub nawet teoretycznie można zdefiniować w tym celu osobną klasę. To ostatnie rozwiązanie w tym przypadku nie ma sensu, ponieważ klasa taka przechowywałaby tylko jedną zmienną. Prezentowane rozwiązanie jest prostsze i czytelniejsze.
Warto zaznaczyć, że wracanie do poprzednich diagramów jest jak najbardziej akceptowalną praktyką. Teraz jednak postaramy się trzymać diagramów wcześniej ustalonych.
Dla zmiennych klasy Wąż
również skorzystamy z getterów i setterów. Za ich pomocą będziemy pobierać i ustawiać wartość zmiennych zawierających informacje o położeniu głowy węża. Inną ważną zmienną jest zmienna przechowująca liczbę punktów. Wąż powinien bowiem przechowywać także informację o położeniu swojego ogona.
W tym miejscu dochodzimy do ważnego pytania, na które musimy jednoznacznie odpowiedzieć. W jaki sposób wykryjemy kolizje zachodzące pomiędzy głową a ogonem?
Zrobimy to tak, że wąż będzie sprawdzał, czy dany punkt na planszy, na który chce się przemieścić, zawiera ogon. Jeśli zawiera, to wtedy gracz przegrywa i wyświetla się wynik punktowy. Jeśli jednak nie, to gra toczy się dalej. Dlatego też informacja o tym, czy dane pole zawiera ogon czy też go nie zawiera, będzie przechowywana w ramach następnej klasy – Plansza
.
Wróćmy jednak do klasy Wąż
.
Ta, ostatecznie, będzie wyglądać w następujący sposób:
![Ilustracja przedstawia klasę w postaci zielonego prostokąta o tytule: Wąż. Posiada ona zmienne: -liczbaPunktów, -pozycjaWęża. Metody: +sprawdźWynik(), +ustawWynik(), +zmieńKierunek(), +przesuń(), +sprzwdźPozycję(), +ustawPozycję(), +zjedzOwoc().](https://static.zpe.gov.pl/portal/f/res-minimized/R1bhKJ7hv06WZ/1662544129/XWxGesyL6ZUXuQ6sQ4gofmf2AZ3XhP1r.png)
Będzie w niej zdefiniowanych siedem metod. Metoda sprawdzWynik()
zwraca aktualny wynik punktowy gracza. Metoda ustawWynik()
ma za zadanie ustawienie aktualnego wyniku na określoną wartość. Metody zmienKierunek()
i przesun()
odpowiadają za zmianę kierunku poruszania się węża oraz za jego przesuwanie. Metody sprawdzPozycje()
i ustawPozycje()
posłużą odpowiednio do uzyskania informacji o aktualnej pozycji węża oraz do ustawiania tej pozycji. Metoda zjedzOwoc()
będzie wywoływana w momencie, gdy wąż natrafi na umieszczony na planszy owoc.
Kolejną, wcześniej wspomnianą klasą, będzie klasa Plansza
. W niej musimy zdefiniować samą wielkość planszy oraz informację o tym, czy na danym polu znajduje się owoc, ogon, czy pusta plansza.
Już na etapie projektowym natrafiliśmy na problem dotyczący tego, w jaki sposób będą definiowane pola planszy. Czy klasa Plansza
powinna składać się z tablicy dwuwymiarowej, czy może jednak być pewnego rodzaju listą?
Najprościej jest utworzyć kolejną klasę o nazwie Pole
. W polu tym zostanie zdefiniowana zmienna, której wartością będzie obiekt klasy Owoc
lub null
. Wynikiem naszych rozważań są dwie klasy:
![Ilustracja przedstawia klasę w postaci zielonego prostokąta o tytule Plansza, ze zmiennymi: +rozmiarXPlanszy, +rozmiarYPlanszy, +pole[][]. Metody: +losujPlansze(), zresetujPlansze(), zaktualizujOgonWęża(). Obok znajduje się klasa: Pole posiadająca zmienne: +owoc.](https://static.zpe.gov.pl/portal/f/res-minimized/RDJZhtH0JD39r/1662544130/AR0iWIUO2MdgNFv9mVo7uk02Y5tJ1X4B.png)
Klasa Pole
również musi zostać wpisana do diagramu pakietów. Uzupełniony pakiet „Zachowanie Rozgrywki” przyjąłby następującą postać:
![Ilustracja przedstawia diagram pakietów w postaci ikony folderu podpisanym jako: Zachowanie rozgrywki. Posiada ona wewnątrz takie klasy jak: Owoc, Wąż, Plansza, Pole.](https://static.zpe.gov.pl/portal/f/res-minimized/RSS0E4Bzyh1wA/1662544130/Rg5Q5LdLo1zSQI7srSHLuQ2CfbrLVDi5.png)
Ostatnią klasą, którą będziemy omawiać, jest klasa o nazwie Wyświetlanie Grafiki
. Klasa ta korzystać będzie z informacji, które otrzyma z klasy Plansza
. Nie będzie ona miała rozbudowanego projektu, ponieważ samo działanie tej klasy nie jest złożone. Odpowiednia metoda przyjmie za argument klasę Pole
i klasę Wąż
, a potem na ich podstawie wygeneruje obraz.
![Ilustracja przedstawia klasę w postaci zielonego prostokąta o tytule: WyświetlanieGrafiki. Posiada metodę: +wyświetlGrę().](https://static.zpe.gov.pl/portal/f/res-minimized/R1Ez740LQXNaq/1662544130/2ZpawfcTd2yeHruOakNkpJxkWQvCPoCF.png)
W diagramie możemy także umieszczać informację o typie zmiennej.
Przykład, który agreguje wszystkie opisane wcześniej klasy w jeden diagram wraz z typami danych:
![Ilustracja przedstawia klasy w postaci zielonych prostokątów: Klasa: ObługaWejścia z metodą: +zinterpretujWciśniętyPrzycisk(). Klasa Wąż z zmiennymi: -liczbaPunktów : int, -pozycjaWęża : point. Metody: +sprawdźWynik(), +ustawWynik(), +zmieńKierynek(), +przesuń(), +sprawdźPozycję(), +zjedzOwoc(). Klasa Owoc, zmienne: -liczbaPunktów : int, metody: sprawdźPunkty(), ustawPunkty(). Klasa WyświetlanieGrafiki z metodą: wyświetlGrę(). Klasa Plansza z zmiennymi: +rozmiarXPlanszy : int, +rozmiarYPlanszy : int, +pole[][]: Pole, oraz z metodami: +losujPlansze(), +zresetujPlansze(), +zaktualizujOgonWęża(). Klasa Pole z zmienną: owoc: Owoc.](https://static.zpe.gov.pl/portal/f/res-minimized/R6q2aP3rjaESJ/1662544130/QXWfvlLyyuejY14hhQeXJg8riZSQqqkf.png)
Kompletny diagram, wraz z uzupełnionymi wartościami początkowymi tam, gdzie jest to uzasadnione.
![Ilustracja przedstawia klasy w postaci zielonych prostokątów: ObługaWejścia z metodą: +zinterpretujWciśniętyPrzycisk(). Klasa Wąż z zmiennymi: -liczbaPunktów : int=0, -pozycjaWęża : Point=null. Metody: +sprawdźWynik(), +ustawWynik(), +zmieńKierynek(), +przesuń(), +sprawdźPozycję(), +zjedzOwoc(). Klasa Owoc, zmienne: -liczbaPunktów : int=0, metody: sprawdźPunkty(), ustawPunkty(). Klasa WyświetlanieGrafiki z metodą: wyświetlGrę(). Klasa Plansza z zmiennymi: +rozmiarXPlanszy : int, +rozmiarYPlanszy : int, +pole[][]: Pole, oraz z metodami: +losujPlansze(), +zresetujPlansze(), +zaktualizujOgonWęża(). Klasa Pole z zmienną: owoc: Owoc=null.](https://static.zpe.gov.pl/portal/f/res-minimized/R4erBYpXojo9Y/1662544131/15Cy0zPsrbzGLgRg7T1cBZhPQvBKSu1i.png)
W klasie Wąż
została zdefiniowana zmienna, która jest obiektem klasy Point
. W założeniu chodziło tutaj o klasę, która służy do oznaczania punktów w przestrzeni dwuwymiarowej. Jednak aby uprościć i uogólnić nasz diagram na wszystkie języki programowania, skorzystamy z takiej wersji:
![Ilustracja przedstawia klasę w postaci zielonego prostokąta: Wąż. Posiada ona zmienne: -liczbaPunktów : int=0, -pozycjaWężaX : int=0, -pozycjaXWężaY : int=0. Metody: +sprawdźWynik(), +ustawWynik(), +zmieńKierunek(), +przesuń(), +sprzwdźPozycję(), +ustawPozycję(), +zjedzOwoc().](https://static.zpe.gov.pl/portal/f/res-minimized/R8p1yIxmJ7rdd/1662544131/2x9WXC99qNVrn7I1DqjBNfSsd4VCU7XT.png)
Dla zwiększenia czytelności zaznaczymy jeszcze związki pomiędzy klasami. Najpierw przejdźmy do omówienia poszczególnych związków. Dostępnych jest 5 różnych związków.
Przerywana strzałka oznacza zależność. Używa się jej w momencie, gdy obiekty jednej klasy korzystają z obiektów drugiej klasy w sposób nieciągły. W naszym przypadku klasa
Wąż
będzie korzystać z obiektów klasyOwoc
tylko czasami, a nie co każdą klatkę animacji. Na diagramie oznaczylibyśmy to w następujący sposób:
![Ilustracja przedstawia zależność klasy Wąż od klasy Owoc poprzez przerywaną strzałkę.](https://static.zpe.gov.pl/portal/f/res-minimized/Rjhp7pQejv9ak/1662544131/JvTyswaE4rLJwWVM5CuZJhx4M7OzDz2h.png)
Pojedyncza linia, która oznacza asocjację, czyli sytuację, gdy obiekt danej klasy wykorzystuje obiekty innej klasy nie ciągle, ale przez dłuższy czas. W naszym diagramie nie ma takiej sytuacji, więc posłużymy się przykładem spoza niego.
![Ilustracja przedstawia asocjację klasy Pracownik z klasą Stanowisko poprzez połączenie klas prostą.](https://static.zpe.gov.pl/portal/f/res-minimized/R1XEuttoH1eav/1662544132/1JfKKue6xrEXRVMzvqefco9rxGqMMJI1.png)
Jeden pracownik ma jedno stanowisko, na którym pracuje przez dłuższy czas, ale w każdym momencie może to stanowisko zmienić.
Linia zakończona pustym rombem oznacza agregację częściową. W naszym diagramie również nie ma dobrego przykładu obrazującego taką zależność. Dlatego też skorzystamy z przykładu spoza naszego diagramu klas:
![Ilustracja przedstawia agregacje częściową klas Widelec i Talerz z klasą Zmywarka poprzez strzałki z kształtem pustego rombu na ich końcach.](https://static.zpe.gov.pl/portal/f/res-minimized/RhhllEfwBrzIr/1662544132/1R4xBV1A1xQThNOft7JEdIOM7UdOQImF.png)
Agregacja ta polega na tym, że element częściowy nie jest zależny od elementu głównego – element częściowy może bez problemu istnieć bez elementu głównego, a jeden element częściowy może należeć do wielu elementów głównych.
Talerz i widelec istnieją bez zmywarki, a zmywarka wcale nie potrzebuje do działania talerza i widelca. Analogicznie możemy dodać do tego:
![Ilustracja przedstawia agregacje częściową klas widelec i Talerz z klasami Zmywarka oraz StosBrudnychNaczyń poprzez strzałki z kształtem pustego rombu na ich końcach.](https://static.zpe.gov.pl/portal/f/res-minimized/R1NsopK6Uwciy/1662544132/1QGHpccDjpLwAQd8cIk69YEt4cZEZAJM.png)
Do stosu brudnych naczyń wcale nie musi należeć widelec, ani talerz – sam StosBrudnychNaczyń może być pusty i czekać jedynie na uzupełnienie.
Linia zakończona zamalowanym rombem to agregacja całkowita, nazywana czasami kompozycją. Jest podobna do agregacji częściowej. Ten typ agregacji charakteryzuje się tym, że istnienie klasy częściowej zależy od istnienia klasy głównej.
![Ilustracja przedstawia klasy Wąż, Owoc, Pole oraz Plansza z wypełnionymi zmiennymi oraz metodami. Klasa wąż jest zależna od klasy Owoc (Strzałka z przerywaną linia). Klasa owoc jest w pełnej agregacji z klasą Pole (Strzałka z czarnym rombem na jej końcu). Klasa Pole jest w pełnej agregacji z klasą Plansza (Strzałka z czarnym rombem na jej końcu).](https://static.zpe.gov.pl/portal/f/res-minimized/R3etQjWWXpKmw/1662544132/1gEgtXQf9wk2cMz5ij1c7lG8V0bi3kbG.png)
Na naszym diagramie zaznaczylibyśmy to w ten sposób – klasa Owoc
może istnieć tylko w ramach klasy Pole
i nigdy nie może istnieć bez niej. Analogicznie klasa Pole
występuje jedynie w ramach klasy Plansza
i nigdy nie będzie występowała samodzielnie.
Ostatnim rodzajem związku jest pusta strzałka, która oznacza dziedziczenie. To dokładnie to samo, co dziedziczenie w językach programowania. Na naszym diagramie nie znajdziemy takich przypadków, jednakże możemy posłużyć się dwoma przykładami:
![Ilustracja przedstawia dwa rzędy po trzy klasy. Od każdej klasy wychodzi strzałka z pustym trójkątem na końcu oznaczająca dziedziczenie. Rząd pierwszy: Klasa Pies dziedziczy klasę Ssak. Klasa Ssak dziedziczy klasę Zwierzę. Rząd drugi: Klasa Uczeń Liceum dziedziczy klasę Nastolatek. Klasa Nastolatek dziedziczy klasę Człowiek.](https://static.zpe.gov.pl/portal/f/res-minimized/R1LU9rjoz3GAK/1662544133/wiSOvPZAtZm4rCm7IY4B6jjZw2cb69By.png)
Pies
dziedziczy po Ssaku
, który dziedziczy po Zwierzęciu
. W ten sposób każdy Pies
otrzymuje cechy Ssaka
. Każdy Ssak
z kolei otrzymuje cechy zwierzęcia
.
Uczeń Liceum
dziedziczy po Nastolatku
, otrzymując jego właściwości, analogicznie Nastolatek
dziedziczy po Człowieku
jakiś zbiór zdolności.
Po wprowadzeniu wszystkich zależności, nasz diagram klas wygląda następująco:
![Ilustracja przedstawia zależności pomiędzy klasami. Klasa ObsługaWejścia bez zależności. Klasa Wąż zależna od klasy Owoc. Klasa Owoc w agregacji całkowitej z klasą Pole. Klasa Pole w agregacji całkowitej z klasą Plansza. Klasa WyświetlanieGrafiki bez zależnosci.](https://static.zpe.gov.pl/portal/f/res-minimized/R1QSmOMBI0eJf/1662544134/2LVdVfh8hHZ8p1H9lE4gbQzPuB8M35rV.png)
Teraz gdy już znasz wszystkie związki, zastanów się, do jakich klas powinniśmy podłączyć klasę Wyświetlanie Grafiki
i ObsługaWejścia
.
Związki od „najsłabszego” do „najsilniejszego” możemy pogrupować następująco:
![Ilustracja przedstawia związki pomiędzy klasami od najsłabszego do najsilniejszego. 1. Zależność, strzałka przerywaną prostą. 2. Asocjacja, prosta. 3. Agregacja częściowa, strzałka z pustym rombem na jej końcu. 4. Agregacja całkowita/kompozycja, strzałka z czarnym rombem na jej końcu. Dziedziczenie, strzałka z pustym trójkątem na jej końcu.](https://static.zpe.gov.pl/portal/f/res-minimized/RvWkioj1OtJ8P/1662544135/2MPdleG1LaxyvZVaH0zSnlNzJAOsk6Us.png)
Czy to już wszystkie potrzebne nam metody? Niekoniecznie. Spójrzmy na diagram klas i zastanówmy się, skąd będziemy wiedzieć, gdzie jest ogon węża.
Odpowiedź brzmi – nie będziemy wiedzieć. Z samej klasy Wąż
jesteśmy w stanie wywnioskować obecną pozycję głowy węża. Możemy teoretycznie zapamiętywać poprzednie pozycje i na tej podstawie dalej dokonywać obliczeń, jednakże nie jest to coś, co uwzględniliśmy na samym diagramie.
Najprościej będzie podjąć następujące kroki:
Wąż przesuwając się na dane pole, będzie ustawiał zmienną na wartość równą
- liczbaPunktów
.Poruszenie się węża będzie zwiększać wartość wszystkich ujemnych pól o jeden. Ostatecznie otrzymamy następujący schemat ruchu:
![Zrzut ekranu przedstawia fragment arkusza kalkulacyjnego. Kolumna wypełniona jest zerami, kolumna druga: 0, -1. 0, 0, 0, 0, kolumna trzecia: 0, -2, -3, -4, 0, 0, kolumna czwarta, 0, 0, 0, -5 (zaznaczona kolorem żółtym), 0, 0, kolumna piąta wypełniona zerami.](https://static.zpe.gov.pl/portal/f/res-minimized/R1g5cKt0zkEOG/1662544135/2i5StsxTCw6pDFnwfmFDlPLGwb7F4yOY.png)
0 | 0 | 0 | 0 | 0 |
0 | -1 | -2 | 0 | 0 |
0 | 0 | -3 | 0 | 0 |
0 | 0 | -4 | -5 | 0 |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 |
Pole zaznaczone na żółto oznacza głowę. Wartość -5 to obecna liczba punktów na minusie, a kolejne ujemne wartości to ogon.
W kolejnym ruchu plansza wyglądałaby następująco:
![Zrzut ekranu przedstawia fragment arkusza kalkulacyjnego. Kolumna wypełniona jest zerami, kolumna druga: wypełniona zerami kolumna trzecia: 0, -1, -2, -3, 0, 0, kolumna czwarta, 0, 0, 0, -4, 0, 0, kolumna piąta: 0, 0, 0, -5 (zaznaczona kolorem żółtym), 0, 0.](https://static.zpe.gov.pl/portal/f/res-minimized/R143tfXXNzmvE/1662544136/1pZaJZa8BraJl7sId5WvhC99WG4f8792.png)
0 | 0 | 0 | 0 | 0 |
0 | 0 | -1 | 0 | 0 |
0 | 0 | -2 | 0 | 0 |
0 | 0 | -3 | -4 | -5 |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 |
Zatem każdy element Planszy
, czyli każda klasa Pole,
powinny mieć dodatkową zmienną, która będzie służyła do śledzenia wartości na danym polu.
Oznacza to również, że musimy poprawić nasz schemat poprzez dodanie odpowiedniego związku pomiędzy klasą Wąż
, a klasą Plansza
.
Pamiętajmy, że nie ma żadnej zmiennej odpowiedzialnej za kierunek ruchu węża, która powinna być obecna w klasie Wąż
. Dlatego umieśćmy ją jako atrybut w ramach klasy Wąż
.
W dodanym związku elementem głównym jest Plansza
, ponieważ to ona – na podstawie informacji dostarczanych przez klasę Wąż
– modyfikuje swoje zmienne.
![Ilustracja przedstawia zależności pomiędzy klasami. Klasa ObsługaWejścia zależna od klasy Wąż. Klasa Wąż zależna od klasy Owoc. Klasa Owoc w agregacji całkowitej z klasą Pole. Klasa Pole w agregacji całkowitej z klasą Plansza. Klasa Wąż zależna od klasy Plansza. Klasa WyświetlanieGrafiki w agregacji częściowej z klasami Wąż oraz Plansza.](https://static.zpe.gov.pl/portal/f/res-minimized/R1EPJM1z6PZia/1662544136/12iGbEgX6N3Bo00y1MJRSBmKhVHMGH3Z.png)
Poprzez ciągłe dodawanie elementów do naszego diagramu chcemy pokazać, że jest to proces, który w przypadku bardziej skomplikowanych projektów może trwać całymi tygodniami. W trakcie implementacji zawsze jednak może dojść do sytuacji, gdy będziemy potrzebować jakiejś dodatkowej zmiennej albo kolejnej metody. I jest to, oczywiście, normalna sytuacja. Nie należy jednak zakładać, że takie przypadki z góry dopuszczamy i się nimi nie przejmujemy, ponieważ wtedy sens robienia diagramu klas się zatraca.
Diagram obiektów
Diagram ten jest podobny do diagramu klas, stworzymy go więc na jego podstawie. Diagram ten pokazuje kilka przykładowych obiektów stworzonych z naszych klas, a także sposób, w jaki są one ze sobą powiązane.
![Ilustracja przedstawia zależności pomiędzy klasami. Klasa ObsługaWejscia zależna od klasy Wąż. Klasa Wąż zależna od klas Owoc 1 oraz Plansza. Klasa Owoc w agregacji całkowitej z klasą Pole 0, 2. Klasa pole 0, 2 w agregacji całkowitej z klasą Plansza. Klasa Pole 0, 1 w agregacji całkowitej z klasą Plansza. Pole 0, 0 w agregacji całkowitej z klasą Plansza. Klasa WyświetlanieGrafiki w agregacji częściowej z klasami Wąż oraz Plansza.](https://static.zpe.gov.pl/portal/f/res-minimized/RzwYWG7eM4g6e/1662544136/1ITFBXlc4zvUVDgT08PLKR7DpxfcVdYa.png)
Na diagramie tym umieszczamy konkretne przykładowe wartości, którymi w prosty sposób możemy zobrazować, jak będzie zachowywał się nasz program.
Dodatkową informacją, jaką możemy umieścić na diagramie obiektów, jest informacja o krotnościach związków, które możemy znać z diagramów ERdiagramów ER, które z kolei wykorzystywane są podczas budowania baz danych.
![Ilustracja przedstawia klasę Owoc 1 posiadającą zmienna: -liczbaPunktów=5 oraz metody: +sprawdźPunkty() w agregacji całkowitej z klasą Pole 0, 2. Na początku oraz końcu strzałki pełnej agregacji ( strzałka z czarnym rombem na jej końcu) znajdują się liczby 1. Klasa Pole 0, 2 zawiera zmienne: +Owoc=Owoc1 oraz +wartośćPola=0.](https://static.zpe.gov.pl/portal/f/res-minimized/Rip39I73fv8rP/1662544136/18p7s2RaktzkKNGcQwmJerD1NcFPAqle.png)
Tak zapisana informacja oznacza, że każdemu Polu
odpowiada jeden i tylko jeden Owoc
. Tak samo możemy odczytać, że każdemu Owocowi
odpowiada jedno i tylko jedno Pole
. Pozostaje więc pytanie, która jedynka tyczy się której informacji?
Zasada jest taka, że patrzymy „z perspektywy” danej klasy, na klasę z nią połączoną i ta liczba „bliżej nas” oznacza, ile tych drugich klas będzie połączonych z naszą klasą.
Dlatego też patrząc z perspektywy obiektu Plansza
, widzimy, że będziemy mieli z nim połączonych n
obiektów klasy Pole
.
![Ilustracja przedstawia zależności pomiędzy klasami. Klasa Pole 0,1 w agregacji całkowitej z klasą Plansza. Na strzałce agregacji całkowitej od strony klasy Pole 0 , 1 znajduje się liczba 1, a od strony klasy Plansza znajduje się mała litera n. Klasa Pole 0,0 w agregacji całkowitej z klasą Plansza. Na strzałce agregacji całkowitej od strony klasy Pole 0, 0 znajduje się liczba 1, a od strony klasy Plansza znajduje się mała litera n.](https://static.zpe.gov.pl/portal/f/res-minimized/Rx8fAM4DPb080/1662544137/1crftuWWK1SZbDNiOkCcJvPUj3UvVhd8.png)
Cały nasz diagram obiektów mógłby przyjąć następującą formę:
![Ilustracja przedstawia zależności pomiędzy klasami. Na początki oraz zakończenia strzałek zależności znajdują się oznaczenia. Klasa ObsługaWejścia zależna od klasy Wąż. Na strzałce zależności, na jej początku oraz końcu znajduje się oznaczenie 1. Klasa Wąż zależna od klasy Owoc 1. Na strzałce zależności, na jej początku oraz końcu znajduje się oznaczenie 1. Klasa Owoc 1 w agregacji całkowitej z klasą Pole 0, 2. Na strzałce agregacji na jej początku oraz końcu znajduje się oznaczenie 1. Klasy Pole0, 2, Pole 0, 1, Pole 0, 0 w agregacji całkowitej z klasą Plansza. Na strzałce pełnej agregacji, od strony klas Pole0, 2, Pole 0, 1, Pole 0, 0 znajdują się oznaczenia 1, a od strony klasy Plansza znajduje się oznaczenie małej litery n. Klasa Wąż zależna od klasy Plansza. na strzałce zależności po obu stronach znajduje się oznaczenie 1. Klasa Wyświetlanie grafiki w agregacji częściowej z klasami Wąż oraz Plansza. Na strzałkach agregacji od strony klasy Wyświetlanie grafiki znajdują się oznaczenia 1, a od strony klas Wąż oraz Plansza mała litera n.](https://static.zpe.gov.pl/portal/f/res-minimized/RFlhVpmjlB4Sw/1662544137/2Ls9pdEO3hWSqs427pGI2DlkL6YeCCnW.png)
Warto zaznaczyć, że nie jest to jedyna możliwa poprawna forma. Chcieliśmy pokazać użycie klas poprzez stworzenie przykładowych obiektów i to właśnie zrobiliśmy.
Słownik
architekt odpowiadający za zaplanowanie struktury programu oraz za zależności w niej występujące; w większych projektach to on jest odpowiedzialny za obmyślanie wcześniej wspomnianych elementów
inaczej diagram związków encji; diagram, dzięki któremu możemy zobrazować zależności w bazie danych