Flyweight - pyłek - wytłumaczenie

0

Nie rozumiem jak to w końcu jest z tym wzorcem. Mamy np. mapę w grze gdzie są takie elementy jak drzewa i inne pola. Jest klasa wirtualna od której dziedziczą wszystkie obiekty, no i klasę drzewo. Potem jest np. tablica [10][10] i jeśli chcemy ją całą wypełnić drzewami to ustawiamy każdemu polu wskaźnik na obiekt drzewo. Ale jak potem zmieniamy parametry jak położenie x,y jeśli wszystkie obiekty na mapie to tak naprawdę jeden i ten sam?

0

Zmieniasz wpis w głównej tablicy i informujesz o tym klasę drzewo przekazując starą i nową pozycję.

2

Pyłek jest obiektem niezmiennym z definicji. W niektórych przypadkach możesz go zmienić, jeżeli ma się odnieść do wszystkich obiektów, ale wtedy lepiej zrobić kolejny obiekt o i innych właściwościach i go podmienić. Ale skupmy się na pierwszym przypadku gdy go nie zmieniamy, czyli posiadasz obiekt drzewa o stałych właściwościach który występuje w aplikacji wiele razy. Posiada on kilka NIEZMIENNYCH właściwości. Np:

  • Wskaźnik na teksturę.
  • Wskaźnik na obiekt opisujący kolizję z tym drzewkiem.
  • jakiś boolean czy gracz może na nim wykonać akcję X.

I teraz żeby umieścić je na mapie masz 2 rozwiązania:

  • Tablica 10x10 wyznacza pozycję, tzn sięgasz do tablicy o na pozycję [x][y] i dostajesz obiekt kamień/drzewo/puste_pole. Wiesz jak je wyświetlić, jak przeprowadzić kolizję oraz czy możesz przeprowadzić akcję X, ale jedyna zmiana jaką możesz zrobić podmienić go na inny obiekt. Przykładowo jeżeli akcja X to ścięcie drzewa i gracz ją wykona, podmieniasz wskaźnik w polu z drzewem na wskaźnik na puste_pole. Na tym polu zmienia się tekstura i nie ma już kolizji.

  • Jakaś kolekcja wskaźników na obiekty które posiadają odniesienie do pyłka. Nadal może to być tablica 10x10, ale odwołuje się już do instancji osobnych obiektów. Przykładowo tworzysz obiekt klasy Drzewo która posiada dodatkowe dane jak liczba_jablek, wielkość etc oraz stałą składową klasy na obiekt pyłku dla którego pól tworzysz delegacje. I tak w całej aplikacji masz 100 drzew a każde posiada tylko 1 wskaźnik na teksturę i inne pola pyłku, ale już każde z osobna posiada dane o ilości jabłek czy wielkości. I dla Twojego przykładu taki obiekt może posiadać też dane o pozycji X i Y, z tym że będziesz już miał te dane w 2 miejscach i przy przesuwaniu drzewa będziesz musiał aktualizować je w tablicy i samym obiekcie.

Jak coś niejasne to pytaj.

0

Przykład idiotyczny, bo ten wzorzec tu zwyczajnie nie pasuje. Prędzej jakieś Prototype. Albo jeśli już Flyweight to z obiektami Immutable i copy-on-write, tzn "zmiana" obiektu powoduje utworzenie jego kopii z nowymi wartościami.
Flyweight to jest zwykle N-gleton. Stosuje się go kiedy masz mocno ograniczoną liczbę obiektów i chcesz je sobie cache'ować.

0

Nie zgodzę się. To co przedstawiłeś zrobi nam kopię obiektów a we wzorcu chodzi o to żeby zaoszczędzić pamięć. Jeżeli masz mapkę 1024x1024 to kopiowanie każdego pola na mapie z wieloma właściwościami zapcha pamięć. Pyłek ma temu zapobiec.

0

A to co ty opisałeś łamie podstawowe zasady OOP ;) Jeśli już to dekorowałbym te wzorcowe obiekty dodatkowymi danymi "specyficznymi" dla konkretnego obiektu, czyli trochę jak twoje rozwiązanie numer 2, ale bez żadnych własności statycznych (bo to rozumiem miałeś na myśli mówiąc o stałych polach klasy).

0

Ok, może nie jest to w pełni piękne i super obiektowe, ale tutaj chodzi po pamięć. Jeżeli jestem w 100% pewny że klasa Drzewo będzie posiadała właściwości klasy DrzewoPyłek to tworząc zmienną statyczną zamiast normalną oszczędzam n-1 pól na wskaźnik gdzie n to liczba drzew na mapie. Zakładając mapę taką jak wcześniej sugerowałem to wszystkich pól będzie 1048576 * powiedzmy 4 bajty = 4194304 bajtów. Jeżeli typów pól mamy nawet te 1000 to przy polu statycznym marnujemy 4000 bajtów a nie 4MB.

0

przejmowanie sie pamiecia w tym momencie to dla mnie przedwczesna optymalizacja. Jezeli nie bedzie to odpalal na kalkulatorze to nie ma znaczenia. Jezeli bedzie potrzebowal to rozwiazac to wtedy moze uzyc staticow. Ja bym poszedl @Shalom rozwiazaniem. A jezeli pamiec bedzie bottleneck to wtedy zoptymalizowac to pod wzgledem pamieci (na 99% nie bedize, co to 4 mb do 16GB ramu?)

0

Jeżeli nie chcecie przejmować się pamięcią to po co używać flyweight? Prototyp który zasugerował @Shalom też by zdał egzamin i byłby czystszy. Z tym że dla n właściwości pamięć by spuchła o 4Mb * n, ale dla takiego n=10 to czym jest 44Mb dla 16 Gb?

0

Rozumiem że jeśli pobieram mapę z pliku to mam wtedy w jakiejś tablicy dane o współrzędnych x,y,ID. Wtedy na tej podstawię ustawiam wskaźnik, jeśli wcisnę spację i sprawdzę że zachodzi kolizja z obiektem drzewo na tych koordynatach to wtedy zamieniam tam wskaźnik na puste pole. Czyli normalnie jak miałem w klasie obiekt vector x,y i tworzyłem wiele instancji tego samego obiektu wyświetlanego na widocznej scenie, to teraz to x,y odczytuję z osobnej zmiennej?

1

To co opisał @krzysiek050 to obiekt typu "immutable".
Stosowany w wielowątkowości, ale także w Flyweight.

To czym jest a czym nie jest w kontekście C++ można przeczytać tutaj:
http://www.boost.org/doc/libs/1_56_0/libs/flyweight/doc/tutorial/

1 użytkowników online, w tym zalogowanych: 0, gości: 1