Wzorzec Singleton
Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 71 z 91.
Wzorzec Singleton to kreacyjny wzorzec projektowy, który zapewnia, że klasa ma tylko jedną instancję przez cały cykl życia aplikacji. Zapewnia również globalny punkt dostępu do tej instancji.
Ten wzorzec jest przydatny, gdy potrzebujesz dokładnie jednego obiektu do koordynowania działań w całym systemie, na przykład połączenia z bazą danych, menedżera konfiguracji lub rejestratora. Tworzenie wielu takich instancji marnowałoby zasoby lub powodowało niespójne działanie.
Oto jak zaimplementować Singletona w PHP:
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// Prywatny konstruktor uniemożliwia bezpośrednie tworzenie instancji
}
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function query(string $sql): string {
return "Executing: $sql";
}
}
$db1 = Database::getInstance();
$db2 = Database::getInstance();
echo $db1 === $db2 ? "Same instance" : "Different instances";
Wynik:
Same instanceWzorzec opiera się na trzech kluczowych elementach: prywatnym konstruktorze, który uniemożliwia bezpośrednie użycie new, właściwości statycznej, która przechowuje jedyną instancję, oraz metodzie statycznej, która tworzy instancję przy pierwszym wywołaniu i zwraca ją przy kolejnych wywołaniach.
Aby Singleton był naprawdę niezawodny, należy również zapobiec klonowaniu i deserializacji:
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
Wyzwanie
ŁatwyZbudujmy menedżer konfiguracji z użyciem wzorca Singleton. W rzeczywistych aplikacjach zazwyczaj chcesz mieć jedno źródło prawdy dla ustawień konfiguracji: wiele obiektów konfiguracji mogłoby prowadzić do niespójnego działania systemu.
Rozmieścisz kod w dwóch plikach:
Config.php: Utwórz klasęConfig, która implementuje wzorzec Singleton. Menedżer konfiguracji powinien:- Przechowywać ustawienia w prywatnej właściwości będącej tablicą
- Mieć prywatny konstruktor, który inicjalizuje pustą tablicę ustawień
- Udostępniać statyczną metodę
getInstance(), która zwraca jedyną instancję - Uniemożliwiać klonowanie, ustawiając metodę
__clone()jako prywatną - Zawierać metodę
set(string $key, string $value): voiddo zapisywania ustawienia - Zawierać metodę
get(string $key): ?string, która zwraca wartość dla klucza lubnull, jeśli klucz nie istnieje - Zawierać metodę
getAll(): array, która zwraca wszystkie ustawienia
main.php: Dołącz plik Config. Otrzymasz dwa dane wejściowe: klucz i wartość.Pobierz instancję Config i ustaw domyślne ustawienie z kluczem
"app_name"i wartością"MyApp".Pobierz drugie odwołanie do instancji Config (ponownie używając
getInstance()) i użyj go do ustawienia kolejnego ustawienia przy użyciu klucza i wartości z danych wejściowych.Na koniec sprawdź, czy Singleton działa poprawnie:
- Wypisz
"Same instance: true"lub"Same instance: false"w zależności od tego, czy oba odwołania wskazują ten sam obiekt (użyj===do porównania) - Wypisz
"Settings count: [count]", pokazując całkowitą liczbę zapisanych ustawień (użyjcount()na wynikugetAll()) - Wypisz
"App name: [value]", pokazując ustawienie app_name pobrane przez drugie odwołanie
- Wypisz
To wyzwanie pokazuje główną zaletę wzorca Singleton: niezależnie od tego, ile razy wywołasz getInstance(), zawsze otrzymasz ten sam obiekt, dzięki czemu wszystkie części aplikacji współdzielą ten sam stan konfiguracji.
Spróbuj swoich sił
<?php
require_once 'Config.php';
// Odczytaj dane wejściowe
$key = trim(fgets(STDIN));
$value = trim(fgets(STDIN));
// TODO: Pobierz instancję Config i ustaw "app_name" na "MyApp"
// TODO: Uzyskaj drugie odwołanie do Config, ponownie używając getInstance()
// TODO: Użyj drugiego odwołania, aby ustawić wartość ustawienia na podstawie $key i $value z danych wejściowych
// TODO: Sprawdź, czy Singleton działa:
// - Wypisz "Same instance: true" lub "Same instance: false" na podstawie porównania ===
// - Wypisz "Settings count: [count]", pokazując łączną liczbę ustawień
// - Wypisz "App name: [value]", pokazując wartość app_name pobraną przez drugie odwołanie
?>Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe $thisMetodyWłaściwościKonstruktor (__construct)Destruktor (__destruct)Powtórka — prosty kalkulator4Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe parent::Przesłanianie metodSłowo kluczowe finalKlasy abstrakcyjnePowtórzenie – hierarchia pracowników7Enkapsulacja
Public, protected, privateModyfikatory dostępu w szczegółachGettery i setteryUkrywanie informacjiPromocja parametrów konstruktora (8.0)Podsumowanie — system ewidencji studentów2Przestrzenie nazw i autoloading
Wprowadzenie do przestrzeni nazwSłowo kluczowe useStandard autoloadingu PSR-4Autoloader ComposeraPodsumowanie – uporządkowany projekt5Interfejsy i kontrakty
Wprowadzenie do interfejsówImplementowanie interfejsówImplementowanie wielu interfejsówInterfejs a klasa abstrakcyjnaPodpowiadanie typów za pomocą interfejsówPodsumowanie — kalkulator kształtów8Metody magiczne
Wprowadzenie do metod magicznych__toString i __debugInfo__get, __set, __isset, __unset__call i __callStatic__clone i klonowanie obiektów__serialize i __unserializePodsumowanie — własna kolekcja11System typów i obsługa błędów
Deklaracje typówTypy nullableTypy sumy i przecięciaKlasy wyjątkówNiestandardowa hierarchia wyjątkówTry, Catch, FinallyPodsumowanie — walidator formularzy14Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Właściwości klas
Właściwości instancji a właściwości statyczneStałe w klasachMetody i właściwości statyczneWłaściwości prywatne i chronioneWłaściwości tylko do odczytu (PHP 8.1)Podsumowanie — menedżer kont bankowych6Polimorfizm
Ponowne omówienie nadpisywania metodPolimorfizm za pomocą interfejsówPodpowiedzi typów i typy sumyPóźne wiązanie statycznePodsumowanie — procesor płatności9Cechy
Wprowadzenie do cechKorzystanie z wielu cechRozwiązywanie konfliktów cechMetody abstrakcyjne w cechachCechy a dziedziczenie12Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec StrategyPoćwicz samodzielnie: Kompilator PHP online