Wzorce projektowe: Singleton w Swift

Na temat Singletona chyba każdy ma swoje własne zdanie. Dla jednych jest ulubionym wzorcem, a dla innych Singleton jest przez wiele osób uznawany jako antypattern. Prawda jak zwykle leży pewnie gdzieś po środku i jeśli używamy tego wzorca z głową, to architektura aplikacji nie powinna na tym ucierpieć.

Opis wzorcahttp://pl.wikipedia.org/wiki/Singleton_(wzorzec_projektowy)

Podobnie jak w Objective-C, tak i w Swift mamy kilka możliwości jak zaimplementować Singleton. Mnie osobiście przypadła do gustu poniższa opcja.

//  Singleton.swift
//  Singleton
 
import Foundation
 
private let _singleton = Singleton() // prywatna stała, widoczna jedynie w pliku, w którym ją zdefiniowano
 
class Singleton {
    class var sharedInstance: Singleton {
        return _singleton;
    }
 
    private init() {} // chowamy inicjalizator przed dostępem z zewnątrz
}

Jak widzicie, za bardzo się nie namęczyłem, tworząc singleton w Swift. Kod prosty, przejrzysty i przyjemny. Ale żeby udowodnić, że to jednak działa, dodam do tej klasy trochę kodu odpowiedzialnego za wyświetlenie liczby stworzonych instancji.

//  Singleton.swift
//  Singleton
 
import Foundation
 
private let _singleton = Singleton() // prywatna stała, widoczna jedynie w pliku, w którym ją zdefiniowano
 
class Singleton {
    class var sharedInstance: Singleton {
        return _singleton;
    }
 
    var counter = 0;
 
    private init() {
        counter++;
        NSLog("Singleton init, counter: %d", counter);
    }
 
    func showCounter() {
        NSLog("Show counter = %d", counter);
    }
}

Teraz wypadałoby całość przetestować w jakimś kontrolerze:

...
NSLog("Getting first instance");
let s1 = Singleton.sharedInstance;
s1.showCounter();
 
NSLog("Getting second instance");
let s2 = Singleton.sharedInstance;
s2.showCounter();
 
NSLog("Getting third instance");
let s3 = Singleton.sharedInstance;
s3.showCounter();
...

Rezultat działania, jaki zobaczymy w logach będzie następujący:

...
2015-01-26 23:11:25.277 Singleton[88412:12310773] Getting first instance
2015-01-26 23:11:25.278 Singleton[88412:12310773] Singleton init, counter: 1
2015-01-26 23:11:25.278 Singleton[88412:12310773] Show counter = 1
2015-01-26 23:11:25.278 Singleton[88412:12310773] Getting second instance
2015-01-26 23:11:25.278 Singleton[88412:12310773] Show counter = 1
2015-01-26 23:11:25.278 Singleton[88412:12310773] Getting third instance
2015-01-26 23:11:25.278 Singleton[88412:12310773] Show counter = 1
...

Prawda czyż nie jest to proste i przyjemne? Ale żeby nie było za prosto, to część z was zapyta, ale czy na pewno nie można zrobić czegoś takiego?

let s = Singleton();

Powyższa opcja jest niemożliwa, ponieważ celowo użyliśmy modyfikatora dostępu private przed metodą init.

private init() {}

Dzięki temu, w kodzie aplikacji, nikt nie będzie mógł tak po prostu stworzyć sobie drugiej instancji naszego Singletona.


Projekt Xcode i pliki źródłowe z przykładowym kodem można znaleźć tutaj.


Ten post jest częścią cyklu o wzorcach projektowych w Objective-C i Swift. Strona Wzorce projektowe w Objective-C i Swift – Kompendium  zbiera w jednym miejscu wzorce i przypisane do nich artykuły. Zapraszam do lektury.

Dodaj komentarz