Przygotowanie do rozmowy kwalifikacyjnej na iOS 5 — singletony

May 04 2023
Wzorzec singleton to wzorzec projektowy, który zapewnia, że ​​klasa ma tylko jedną instancję i zapewnia globalny punkt dostępu do tej instancji. Może to być przydatne, gdy klasa musi być udostępniana w wielu częściach aplikacji, ale tworzenie wielu wystąpień klasy nie jest praktyczne ani pożądane.

Wzorzec singleton to wzorzec projektowy, który zapewnia, że ​​klasa ma tylko jedną instancję i zapewnia globalny punkt dostępu do tej instancji. Może to być przydatne, gdy klasa musi być udostępniana w wielu częściach aplikacji, ale tworzenie wielu wystąpień klasy nie jest praktyczne ani pożądane. W systemie iOS wzorzec singleton jest powszechnie używanym wzorcem projektowym.

Pytania do wywiadu

  • Co to jest Singleton i jak jest używany w rozwoju iOS?
  • Czy możesz wyjaśnić wzorzec projektowy Singleton i jego zalety?
  • Jakie są możliwe sposoby zapobiegania wielu instancjom Singletona w środowisku wielowątkowym?
  • Czy możesz podać przykład, kiedy użyłbyś Singletona w swojej aplikacji na iOS?
  • Jak testujecie Singletona na iOS?

Częstym problemem związanym z singletonami jest to, że często nie są one bezpieczne dla wątków. Są często używane z wielu kontrolerów jednocześnie uzyskujących dostęp do pojedynczej instancji.

Tworząc singleton, musisz wziąć pod uwagę dwie rzeczy

  • Instancja powinna być utworzona w sposób zapewniający bezpieczeństwo wątków
  • Powinieneś oznaczyć metodę init klasy jako prywatną, aby zapobiec tworzeniu większej liczby instancji
  • Podczas inicjowania pojedynczej instancji.
  • Podczas odczytów i zapisów w instancji.

Aby zaimplementować wzorzec singleton w Swift, klasa, która musi być singletonem, jest definiowana za pomocą staticsłowa kluczowego, które wskazuje, że klasa ma tylko jedną instancję. Zmienna statyczna służy do przechowywania instancji klasy, a metoda statyczna służy do uzyskiwania dostępu do instancji. Oto przykład klasy singleton w Swift

class Singleton {
		// Swift guarantees initialization is atomic
		// Swift treats the code performing initialization as a critical section
    static let shared = Singleton()
    
    // prevents the creation of additional instances of the class.
    private init() {}
}

let singleton = Singleton.shared

@implementation MySingleton

// Lazy initializer 
+ (instancetype)sharedInstance {
    static dispatch_once_t once;
    static id sharedInstance;
  // The token ensures that init is executed only once in thread safety manner
    dispatch_once(&once, ^{
        _sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}
// Prevent creating new instance of the singleton
- (instancetype)init __attribute__((unavailable("Use +[MyClass sharedInstance] instead")));
+ (instancetype)new __attribute__((unavailable("Use +[MyClass sharedInstance] instead")));
@end

Zalety

  • Zapewnia, że ​​tworzona jest tylko jedna instancja klasy, co może pomóc w oszczędzaniu pamięci i zwiększeniu wydajności.
  • Zapewnia globalny punkt dostępu do wystąpienia klasy, co może ułatwić korzystanie z niego w kodzie.
  • Może być przydatny do implementowania współdzielonych zasobów, takich jak bazy danych lub połączenia sieciowe, które muszą być współużytkowane przez różne części kodu.
  • Może utrudnić testowanie i debugowanie kodu, ponieważ wprowadza stan globalny, który jest współdzielony przez różne części kodu.
  • Utrudnia tworzenie wielu wystąpień klasy do celów testowych lub innych.
  • Może prowadzić do ścisłego sprzężenia i naruszać zasady projektowania obiektowego.
  • Niezbyt dobra opcja dla zadań związanych z sesją użytkownika, ponieważ może być konieczne zniszczenie i utworzenie nowego singletonu, gdy użytkownik się wyloguje.

Istnieje gwarancja 1 na konto (zamiast gwarancji 1 na aplikację). Dostęp nie jest globalny (potrzebna jest sesja użytkownika). Podobnie jak w przypadku singletona, tworzonego leniwie przy pierwszym dostępie, później zawsze zwracana jest ta sama instancja. Na przykład MyUserSession jest tworzony, gdy uwierzytelniony użytkownik rozpoczyna sesję. Musi zostać wstrzyknięty do dowolnego kodu zawierającego dane użytkownika