Jaki jest najprostszy / najczystszy sposób zaimplementowania wzorca singleton w JavaScript?
javascript
function
design-patterns
singleton
Jakub Arnold
źródło
źródło
Odpowiedzi:
Myślę, że najłatwiej jest zadeklarować prosty dosłowny obiekt:
Jeśli chcesz członków prywatnych w swojej instancji singleton, możesz zrobić coś takiego:
Nazywa się to wzorcem modułowym i zasadniczo pozwala enkapsulować prywatne elementy na obiekcie, wykorzystując zamknięcia .
AKTUALIZACJA: Chciałbym dodać, że jeśli chcesz zapobiec modyfikacji obiektu singletonu, możesz go zatrzymać , używając
Object.freeze
metody ES5 .To sprawi, że obiekt będzie niezmienny, zapobiegając jakiejkolwiek modyfikacji jego struktury i wartości.
Dodatkowo chciałbym wspomnieć, że jeśli używasz ES6, możesz bardzo łatwo reprezentować singletona za pomocą ES Modules , a nawet możesz utrzymywać stan prywatny , deklarując zmienne w zakresie modułu :
Następnie możesz po prostu zaimportować obiekt singleton, aby go użyć:
źródło
publicMethod1
zadzwoniłpublicMethod2
?getInstance
metodę statyczną i prywatnego konstruktora - ale IMO to najprostszy sposób na zbudowanie obiektu singleton w JavaScript, a na koniec spełnia ten sam cel - pojedynczy obiekt, którego nie można ponownie zainicjować (nie ma konstruktora, to tylko obiekt) -. Jeśli chodzi o kod, który podłączyłeś, ma on pewne problemy, zamieniaa
ib
deklaruje zmienne i testujea === window
. Twoje zdrowie.Myślę, że najczystsze podejście to:
Następnie możesz wywołać funkcję as
źródło
delete instance.constructor
:x = SingletonClass.getInstance();delete x.constructor;new x.constructor;
Nie jestem pewien, czy zgadzam się na użycie wzorca modułu jako zamiennika wzorca singletonu. Często widziałem singletony używane i nadużywane w miejscach, w których są całkowicie niepotrzebne, i jestem pewien, że wzór modułu wypełnia wiele luk, w których programiści używaliby singletonu, jednak wzór modułu nie jest singletonem.
wzór modułu:
Wszystko zainicjowane we wzorcu modułu dzieje się, gdy
Foo
zostanie zadeklarowane. Ponadto wzorca modułu można użyć do zainicjowania konstruktora, który można następnie utworzyć wiele razy. Chociaż wzorzec modułu jest właściwym narzędziem do wielu zadań, nie jest równoważny z singletonem.wzór singletonu:
skrócona forma długa forma, przy użyciu wzoru modułuW obu wersjach wzorca Singleton, który podałem, sam konstruktor może być używany jako akcesorium:
Jeśli nie czujesz się komfortowo przy użyciu konstruktora w ten sposób, możesz zgłosić błąd w
if (instance)
instrukcji i trzymać się długiej formy:Powinienem również wspomnieć, że wzorzec singletonu dobrze pasuje do domyślnego wzorca funkcji konstruktora:
źródło
var singleton = {}
nie pasuje do tej definicji.var singleton = {}
jest jak zaimplementować singleton w JavaScript .W
es6
:źródło
instance
pole. Ponieważ jest obecnie (instance
ustawiona nathis
) ta klasa może mieć także inne pola, a zamrażanie nie ma sensu.Następujące działa w węźle v6
Testujemy:
źródło
W ES6 właściwym sposobem na to jest:
Lub jeśli nie chcesz, aby błąd był generowany podczas tworzenia drugiej instancji, możesz po prostu zwrócić ostatnią instancję w następujący sposób:
źródło
instance
i_instance
. To tylko konwencja nazewnictwa w językach programowania, którą nazywamy zmiennymi prywatnymi poprzedzonymi znakiem podkreślenia. Podejrzewam, że przyczyną tego, że Twój kod nie działa, jest to, że używaszthis.instance
zamiastMyClass.instance
Jest więcej niż jeden sposób na skórowanie kota :) W zależności od gustu lub konkretnej potrzeby możesz zastosować dowolne z proponowanych rozwiązań. Osobiście wybieram pierwsze rozwiązanie CMS, gdy tylko jest to możliwe (gdy nie potrzebujesz prywatności). Ponieważ pytanie dotyczyło najprostszego i najczystszego, to jest zwycięzca. Lub nawet:
To (cytat z mojego bloga) ...
nie ma większego sensu (mój przykład na blogu też nie), ponieważ nie potrzebuje żadnych prywatnych zmiennych, więc jest prawie taki sam jak:
źródło
this.f(){}
Nie zgadzam się z moją odpowiedzią, zobacz moją drugą .
Zwykle wzorzec modułu (patrz odpowiedź CMS), który NIE jest wzorzec singletonu, jest wystarczająco dobry. Jednak jedną z cech singletonu jest to, że jego inicjalizacja jest opóźniona do momentu, gdy potrzebny jest obiekt. Wzorzec modułu nie ma tej funkcji.
Moja propozycja (CoffeeScript):
Które skompilowane do tego w JavaScript:
Następnie mogę wykonać następujące czynności:
źródło
Krótka odpowiedź:
Ponieważ nieblokujący charakter JavaScript, Singletons w JavaScript są naprawdę brzydkie w użyciu. Zmienne globalne dają również jedną instancję w całej aplikacji bez tych wszystkich wywołań zwrotnych, wzór modułu delikatnie ukrywa elementy wewnętrzne za interfejsem. Zobacz odpowiedź @CMS.
Ale skoro chciałeś singletona…
Stosowanie:
Wyjaśnienie:
Singletony dają więcej niż jedną instancję w całej aplikacji: ich inicjalizacja jest opóźniona do pierwszego użycia. To naprawdę wielka sprawa, gdy masz do czynienia z obiektami, których inicjalizacja jest droga. Drogie zwykle oznacza We / Wy, aw JavaScript We / Wy zawsze oznacza oddzwanianie.
Nie ufaj odpowiedziom, które dają ci interfejs
instance = singleton.getInstance()
, wszystkie pomijają sens.Jeśli nie przyjmą wywołania zwrotnego do uruchomienia, gdy instancja jest gotowa, nie będą działać, gdy inicjator wykonuje operacje we / wy.
Tak, wywołania zwrotne zawsze wyglądają brzydiej niż wywołanie funkcji, które natychmiast zwraca instancję obiektu. Ale znowu: kiedy wykonujesz operacje we / wy, połączenia zwrotne są obowiązkowe. Jeśli nie chcesz wykonywać żadnych operacji we / wy, tworzenie instancji jest wystarczająco tanie, aby zrobić to na początku programu.
Przykład 1, tani inicjator:
Przykład 2, inicjalizacja za pomocą I / O:
W tym przykładzie
setTimeout
podróbka kosztownej operacji we / wy. To pokazuje, dlaczego singletony w JavaScript naprawdę potrzebują wywołań zwrotnych.źródło
Ten przykład wziąłem z wzorców JavaScript, które budują lepsze aplikacje z kodowaniem i wzorami projektowymi. Książka Stoyana Stefanova na wypadek, gdybyś potrzebował prostej klasy implementacji, takiej jak obiekt singltone, możesz użyć natychmiastowej funkcji:
Możesz sprawdzić ten przykład, wykonując następujący test:
Podejście to przechodzi wszystkie przypadki testowe, podczas gdy prywatna implementacja statyczna zakończy się niepowodzeniem, gdy zostanie użyte rozszerzenie prototypu (można to naprawić, ale nie będzie to proste), a publiczna implementacja statyczna mniej wskazana z powodu wystąpienia jest ujawniana publicznie.
jsFiddly demo.
źródło
Myślę, że znalazłem najczystszy sposób na programowanie w JavaScript, ale potrzebujesz wyobraźni. Ten pomysł zaczerpnąłem z techniki pracy w książce „javascript the good parts”.
Zamiast używać nowego słowa kluczowego, możesz utworzyć taką klasę:
Możesz utworzyć instancję powyższego obiektu, mówiąc:
Teraz mając na uwadze tę metodę pracy, możesz utworzyć singleton taki jak ten:
Teraz możesz uzyskać instancję, dzwoniąc
Myślę, że to najładniejszy sposób, ponieważ cała „klasa” nie jest nawet dostępna.
źródło
Zarówno @CMS, jak i @zzzzBov dały wspaniałe odpowiedzi, ale tylko po to, by dodać własną interpretację opartą na tym, że przeszedłem do ciężkiego rozwoju node.js z PHP / Zend Framework, w którym wzorce singletonów były powszechne.
Poniższy kod udokumentowany komentarzem opiera się na następujących wymaganiach:
Mój kod jest bardzo podobny do kodu @ zzzzBov, z tym wyjątkiem, że dodałem do konstruktora łańcuch prototypów i więcej komentarzy, które powinny pomóc osobom pochodzącym z PHP lub podobnego języka w przetłumaczeniu tradycyjnego OOP na JavaScript o charakterze prototypowym. Może nie jest to „najprostsze”, ale uważam, że jest najbardziej odpowiednie.
Zauważ, że technicznie samoczynnie wykonująca się funkcja anonimowa sama w sobie jest Singletonem, co dobrze pokazano w kodzie dostarczonym przez @CMS. Jedynym haczykiem jest to, że nie można modyfikować łańcucha prototypów konstruktora, gdy sam konstruktor jest anonimowy.
Pamiętaj, że w przypadku Javascript pojęcia „public” i „private” nie mają zastosowania, tak jak w PHP lub Javie. Ale osiągnęliśmy ten sam efekt, wykorzystując zasady dostępności zakresu funkcjonalnego Javascript.
źródło
var a = Singleton.getInstance('foo'); var b = new a.constructor('bar');
Nie jestem pewien, dlaczego nikt tego nie poruszał, ale możesz po prostu:
źródło
Najjaśniejszą odpowiedzią powinna być ta z książki Uczenie się wzorców projektowania JavaScript autorstwa Addy Osmani.
źródło
Uważam, że jest to najprostszy / najczystszy i najbardziej intuicyjny sposób, choć wymaga ES7:
Kod źródłowy pochodzi z: adam-bien.com
źródło
new Singleton()
Co jest z tym nie tak?
źródło
Test = Klass; t1 = new Test(); t2 = new Test();
- brak możliwości zmiany nazwy klasy lub wybrania innej przestrzeni nazw.czy mogę włożyć moje 5 monet. Mam funkcję konstruktora, np.
Muszę tylko każdy obiekt utworzony przez ten CF będzie taki sam.
test
źródło
Odkryłem, że jest to najłatwiejszy wzorzec Singleton, ponieważ użycie nowego operatora powoduje, że jest on natychmiast dostępny w ramach funkcji, co eliminuje potrzebę zwracania literału obiektu:
źródło
Oto prosty przykład wyjaśniający wzór singletonu w javascript.
źródło
Potrzebowałem kilku singletonów z:
i tak oto wpadłem na pomysł:
Argumenty muszą być tablicą, aby to działało, więc jeśli masz puste zmienne, po prostu przekaż []
Użyłem obiektu window w funkcji, ale mogłem przekazać parametr, aby utworzyć własny zakres
parametry nazwy i konstrukcji są tylko ciągiem, aby okno [] działało, ale przy prostym sprawdzaniu typów możliwe jest także window.name i window.construct.
źródło
A co powiesz na ten sposób, po prostu upewnij się, że klasa nie będzie znowu nowa.
Dzięki temu możesz użyć
instanceof
op, możesz także użyć łańcucha prototypów, aby odziedziczyć klasę, jest to zwykła klasa, ale nie możesz jej nowego, jeśli chcesz uzyskać instancję, użyjgetInstance
Jeśli nie chcesz narażać
instance
członka, po prostu zamknij go.źródło
Poniżej znajduje się fragment mojego przejścia do implementacji wzorca singletonu. To przyszło mi do głowy podczas wywiadu i czułem, że powinienem to gdzieś uchwycić.
to samo można znaleźć na moim GIST stronie
źródło
źródło
Czy to też nie jest singleton?
źródło
Możesz to zrobić za pomocą dekoratorów, jak w tym przykładzie poniżej dla TypeScript:
Następnie używasz swojego singletona w ten sposób:
W tym piśmie dekoratory nie są łatwo dostępne w silnikach JavaScript. Musisz upewnić się, że środowisko wykonawcze JavaScript ma włączone dekoratory lub użyć kompilatorów takich jak Babel i TypeScript.
Zauważ też, że instancja singleton jest tworzona jako „leniwa”, tzn. Jest tworzona tylko przy pierwszym użyciu.
źródło
Wzór modułu: w „bardziej czytelnym stylu”. Możesz łatwo zobaczyć, które metody są publicznymi, a które prywatnymi
teraz możesz korzystać z metod publicznych takich jak
module.method2 (); // -> Wywołuję metodę prywatną w ramach alertu dotyczącego metody publicznej („cześć, jestem metodą prywatną”)
http://jsfiddle.net/ncubica/xMwS9/
źródło
Singel:
Upewnij się, że klasa ma tylko jedną instancję i zapewnij do niej globalny punkt dostępu.
Wzorzec Singleton ogranicza liczbę wystąpień określonego obiektu do tylko jednego. Ta pojedyncza instancja nazywa się singletonem.
Obiekt Singleton jest implementowany jako natychmiastowa anonimowa funkcja. Funkcja jest wykonywana natychmiast, zawijając ją w nawiasy, a następnie dwa dodatkowe nawiasy. Nazywa się to anonimowym, ponieważ nie ma nazwy.
Przykładowy program,
źródło
Najprostsze / najczystsze dla mnie oznacza również po prostu zrozumienie i brak dzwonków i gwizdków, o czym wiele się mówi w wersji Java dyskusji:
Jaki jest skuteczny sposób na implementację wzorca singleton w Javie?
Odpowiedź, która najlepiej pasuje do najprostszych / najczystszych z mojego punktu widzenia, to:
https://stackoverflow.com/a/70824/1497139
I tylko częściowo można to przetłumaczyć na JavaScript. Niektóre różnice w Javascript są następujące:
Ale biorąc pod uwagę najnowszą składnię ECMA, można zbliżyć się do:
Wzór singletonu jako przykład klasy JavaScript
Przykładowe użycie
Przykład wyniku
źródło
Jeśli jesteś w klasach:
Test:
źródło
Jeśli chcesz korzystać z klas:
Dane wyjściowe dla powyższych będą:
Kolejny sposób pisania Singletona za pomocą funkcji
Dane wyjściowe dla powyższych będą:
źródło