Wiem, że posiadanie zmiennych globalnych lub klas singletonowych tworzy przypadki, które mogą być trudne do przetestowania / zarządzania, i byłem przyłapany na używaniu tych wzorców w kodzie, ale często trzeba je wysyłać.
Czy są więc przypadki, w których zmienne globalne lub singletony są rzeczywiście przydatne w tworzeniu gier?
software-engineering
design-patterns
Lalafur Waage
źródło
źródło
Zdecydowanie niewyczerpująca lista, ale oto:
Cons
Albo za albo przeciw
Plusy
W naszych przenośnych tytułach często używamy „struktury globalnych singletonów”. Tytuły na komputery PC i konsole zwykle polegają na nich mniej; przestawimy się bardziej na architekturę sterowaną zdarzeniami / wiadomościami. To powiedziawszy, tytuły komputerów / konsoli nadal często używają centralnego menedżera tekstur; ponieważ zwykle obejmuje jeden wspólny zasób (pamięć tekstur), ma to dla nas sens.
Jeśli utrzymujesz swój interfejs API względnie czysty, może nie być zbyt strasznie trudne zreformowanie (lub włączenie!) Wzorca singletonu, kiedy potrzebujesz ...
źródło
Mogą być bardzo przydatne, szczególnie podczas prototypowania lub eksperymentalnej implementacji, ale ogólnie wolimy przekazywanie referencji dla struktur podobnych do menedżerów, w ten sposób masz przynajmniej kontrolę nad tym, skąd są dostępne. Największym problemem z globals i singletonami (moim zdaniem) jest to, że nie są one bardzo przyjazne dla wielowątkowości, a kod, który ich używa, jest znacznie trudniejszy do przeniesienia do pamięci nieudostępnionej, takiej jak SPU.
źródło
Powiedziałbym, że sam projekt singletonu wcale nie jest użyteczny. Zmienne globalne mogą być z pewnością przydatne, ale wolałbym, aby były ukryte za dobrze napisanym interfejsem, abyś nie był świadomy ich istnienia. Dzięki singletonom jesteś zdecydowanie świadomy ich istnienia.
Często używam zmiennych globalnych do rzeczy, które wymagają dostępu przez cały silnik. Moje narzędzie wydajności jest dobrym przykładem, do którego dzwonię w całym silniku. Połączenia są proste; ProbeRegister (), ProbeHit () i ProbeScoped (). Ich rzeczywisty dostęp jest nieco trudniejszy i wykorzystuje niektóre zmienne globalne.
źródło
Głównym problemem związanym z globaliami i źle wdrożonymi singletonami są niejasne błędy konstrukcyjne i dekonstrukcyjne.
Więc jeśli pracujesz z prymitywami, które nie mają tych problemów lub są bardzo świadome problemu ze wskaźnikiem. Następnie mogą być bezpiecznie używane.
Globale mają swoje miejsce, podobnie jak goto i nie powinny być odrzucane z ręki, ale powinny być używane ostrożnie.
Dobre wyjaśnienie znajduje się w Przewodniku po stylu Google C ++
źródło
Globalne są przydatne podczas szybkiego prototypowania systemu, który wymaga pewnego stanu między wywołaniami funkcji. Po ustaleniu, że system działa, przenieś stan do klasy i przekształć funkcje w metody tej klasy.
Singletony są przydatne do powodowania problemów sobie i innym. Im bardziej globalny stan wprowadzasz, tym więcej problemów będziesz mieć z poprawnością kodu, obsługą, rozszerzalnością, współbieżnością itp. Po prostu nie rób tego.
źródło
Zwykle zalecam używanie pewnego rodzaju kontenera DI / IoC z niestandardowym zarządzaniem cyklem życia zamiast singletonów (nawet jeśli używasz menedżera czasu życia „pojedynczej instancji”). Przynajmniej wtedy łatwo jest zamienić implementację, aby ułatwić testowanie.
źródło
Jeśli chcesz mieć funkcje oszczędzania pamięci singletona, być może mógłbyś wypróbować wzór wagi lekkiej?
http://en.wikipedia.org/wiki/Flyweight_pattern
Jeśli chodzi o wspomniane powyżej problemy z wieloma wątkami, powinno być dość przewidywanie, aby wdrożyć mechanizm blokowania zasobów, które mogą być współużytkowane między wątkami. http://en.wikipedia.org/wiki/Read/write_lock_pattern
źródło
Singletony to świetny sposób na przechowywanie stanu wspólnego we wczesnym prototypie.
Nie są srebrną kulą i mają pewne problemy, ale są bardzo przydatnym wzorem dla niektórych stanów interfejsu / logiki.
Na przykład w systemie iOS używasz singletonów do uzyskania [UIApplication sharedApplication], w cocos2d możesz użyć go do uzyskania referencji do niektórych obiektów, takich jak [CCNotifications sharedManager], a osobiście zwykle zaczynam od singletonu [Game sharedGame], w którym mogę stan magazynu, który jest współużytkowany przez wiele różnych składników.
źródło
Wow, to mnie interesuje, ponieważ nigdy osobiście nie miałem problemu ze wzorem singletonów. Mój obecny projekt to silnik gry C ++ na konsolę Nintendo DS, a ja implementuję wiele narzędzi dostępu do sprzętu (tj. VRAM Banks, Wifi, dwa silniki graficzne) jako instancje singletonów, ponieważ mają one na celu owijanie globalnego C funkcje w podstawowej bibliotece.
źródło
Tylko wtedy, gdy masz element, który ma tylko jeden kontroler, ale jest obsługiwany przez kilka modułów.
Takich jak na przykład interfejs myszy. Lub interfejs joysticka. Lub odtwarzacz muzyki. Lub odtwarzacz dźwięku. Lub ekran. Lub menedżer zapisywania plików.
źródło
Globale są znacznie szybsze! Idealnie pasowałoby do aplikacji wymagających dużej wydajności, takich jak gry.
Singletony są lepszym globalnym, IMO, a zatem właściwym narzędziem.
Używaj go oszczędnie!
źródło