Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Dobra alternatywa dla Singleton
Forum PHP.pl > Forum > PHP
grzesiek_g
Witam

Mam do napisania klasę (zbiór klas) która będzie odpalona gdzieś na początku kodu. Obojętnie czy to będzie pojedynczy plik php, czy Bootstrap frameworka.

Wymagania:
  • tylko jedna instancja na całe wywołanie
  • dostęp z dowolnego miejsca w kodzie
  • brak zależności od innych klas, nie chcę instalować dodatkowych zależności jak np PHP DI
  • maksymalna uniwersalność, ma działać zarówno z kodem PHP 5.3 jaki i 7.1+

Od razu nasuwa się myśl wykorzystania Singleton, ale ponieważ jest to antywzorzec szukam lepszego rozwiązania.
Najlepiej jakby dało się zrobić coś takiego w wywołaniu:
  1. MyClass::init($config);
  2.  
  3. // w innym pliku
  4. MyClass::setConfig('key', $value);
  5.  
  6. // lub
  7. MyClass::action($parameters);


Mogę prosić o jakieś sugestie?
kayman
rejestr?
Puszy
Demonizowanie Singletona jest bezpodstawne. Wszystko zależy od tego kto go tworzy i co ma wykonywać. Ja osobiście korzystam z Singletonów nawet we frameworkach.
grzesiek_g
Registry, wydaje mi się, że to wyjdzie na to samo z jakością kodu. Jedyne co widzę sensownego w tej roli to Singleton i Dependency Injection.
lukaskolista
Cytat
Demonizowanie Singletona jest bezpodstawne. Wszystko zależy od tego kto go tworzy i co ma wykonywać. Ja osobiście korzystam z Singletonów nawet we frameworkach.

To, że ktoś zrobił coś we frameworku nie oznacza, że jest to poprawne rozwiązanie.

Demonizowanie singletona jest bardzo podstawne i w żadnym stopniu nie zależy od tego kto go tworzy i co ma wykonywać - singleton jest antywzorcem, ponieważ:
1. Przeczy paradygmatowi programowania obiektowego
2. Przeczy innym paradygmatom programowania jak odwrócone sterowanie (IoC) chociaż nie aż tak bardzo jak w przypadku pkt. 1
3. Niesamowicie utrudnia, o ile w niektórych przypadkach uniemożliwia napisanie porządnych testów jednostkowych, trzeba się czasami bardzo nakombinować, żeby napisać test jednostkowy klasy, która zależy od takiego singletona.
4. I teraz miazga dla singletona - singleton nie jest niczym innym, jak globalem - tak tak, singleton to "zmienna" globalna, jest realizowany za pomocą statycznej metody danej klasy natomiast z założenia jest czymś globalnym, a jak powszechnie wiadomo wszystko co globalne w językach obiektowych jest złem.

Porządną alternatywą dla singletona jest po prostu nieużywanie singletona, a poza tym to Registry, Service Container czy Service Locator - kwestia nazwy, idea wspólna.

Cytat
Wymagania:
tylko jedna instancja na całe wywołanie
dostęp z dowolnego miejsca w kodzie
brak zależności od innych klas, nie chcę instalować dodatkowych zależności jak np PHP DI
maksymalna uniwersalność, ma działać zarówno z kodem PHP 5.3 jaki i 7.1+

Niestety, ale przy głupich założeniach nie zrobisz nic porządnego. Skąd w ogóle takie bezsensowane wymaganie jak i 2? Co do 3 to nie bardzo rozumiem, zależności między klasami są czymś naturalnym, ponieważ nawet w rzeczywistości nic nie występuje samo, praktycznie każde "coś" oddziałuje z "czymś" innym. Problem pojawia się, gdy tych zależności robi się za dużo, ale wtedy przychodzą z pomocą odpowiednie techniki refaktoryzacji.
Wymaganie 1 można spokojnie spełnić bez singletona i bez service locatora za pomocą zwykłego DI i utworzenia instancji danej klasy w jakiejś wyższej warstwie.

Cytat
Jedyne co widzę sensownego w tej roli to Singleton i Dependency Injection.
Singleton przeczy DI, bo zamiast wstrzykiwać zależność po prostu odwołujesz się do statycznej metody innej klasy - takie jest założenie singletona.
Pilsener
Potrzeba użycia globala świadczy o złej architekturze aplikacji, nie nadrobisz złej architektury naszym geniuszem Lkingsmiley.png
Jak potrzebujesz używać singletona to go używaj, po co robić obejście dla obejścia? Pierwsze obejście zasad obiektowości - używanie globala by obejść hermetyzację, po co kolejne obejście singletona? Ma to sens na zdrowy rozsądek? Złe + złe nie równa się dobre businesssmiley.png W ten sposób powstają coraz to gorsze "potwory" baaasmiley.gif
A dobrą alternatywą będzie dobre zaprojektowanie kontekstu aplikacji i jego wstrzykiwanie (lub zaimplementowanie jako warstwa abstrakcii) do odpowiednich miejsc.
Puszy
@lukaskolista

Oczywiście masz rację, jest wiele wad singleton lecz nadal twierdzę że w niektórych sytuacjach jest to po prostu proste rozwiązanie, zwłaszcza dla klas które dostarczają utility. Zdaję sobie sprawę z tego że taki kod nie jest w pełni "poprawny" jeżeli chodzi o wszelkie wzorce i wytyczne ale np. nie widzę nic złego w użyciu singletona dla bardziej rozbudowanego loggera.
lukaskolista
@Puszy
A ja widzę, np. nie jesteś w stanie rzetelnie przetestować klasy klienckiej takiego loggera bo po prostu nie da się go zamockować (w mockery niby się da, ale jest to obarczone bardzo dużymi ograniczeniami).
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.