magányos | |
---|---|
Szingli | |
Típusú | generáló |
profik | megszervezi az API-t; implicit módon betölti a megfelelő modulokat a megfelelő sorrendben; helyet hagy egy második hasonló tárgynak |
Mínuszok | bonyolítja a tesztelést, a többszálú kezelést és a késleltetés követését; a singletonok nem függhetnek implicit módon egymástól |
Leírása: Tervezési minták | Igen |
A singleton egy generatív tervezési minta , amely garantálja, hogy egy bizonyos osztály egyetlen példánya lesz egy egyszálú alkalmazásban, és globális hozzáférési pontot biztosít ehhez a példányhoz.
Az osztálynak csak egy példánya van, és globális hozzáférési pontot biztosít hozzá. Amikor megpróbálja létrehozni ezt az objektumot , csak akkor jön létre, ha még nem létezik, ellenkező esetben a rendszer egy már létező példányra hivatkozik, és nem történik új memóriafoglalás. Lényeges, hogy az osztály egy példányát lehessen használni , mivel sok esetben szélesebb körű funkcionalitás válik elérhetővé. Például a leírt osztályösszetevők a felületen keresztül érhetők el , ha ezt a lehetőséget a nyelv támogatja.
Néha szükség van egy globális "magányos" objektumra - nevezetesen egy objektumra ( ), és nem egy objektumhoz ( ) nem társított eljárások halmazára :log().put("Test");logPut("Test");
Ilyen objektumok a program inicializálása során is létrehozhatók. Ez a következő nehézségekhez vezethet:
Ez az opció blokkolja a getInstance() metódust, akár egyetlen példányt hoztunk létre, akár nem. Ez lelassítja a programot, ha gyakran kell Singleton objektumot beszereznie különböző szálakból.
public class Singleton { private static Singleton példány ; privát Singleton () {}; public static synchronized Singleton getInstance () { if ( példány == null ) { példány = new Singleton (); } return instance ; } }A PEP 0318 dokumentumból archiválva 2020. június 3-án a Wayback Machine -nél :
Python példa dekorátorokkal def singleton ( cls ): példányok = {} def getinstance (): ha a cls nincs példányokban : példányok [ cls ] = cls () return példányok [ cls ] return getinstance @singleton class MyClass : ...A PEP 0318 dokumentumból archiválva : 2020. június 3. a Wayback Machine -nél :
Python példa a MetaClasses-on osztály MetaSingleton ( típus ): _instances = {} def __call__ ( cls , * args , ** kwargs ): ha a cls nincs a cls -ben . _instances : cls . _instances [ cls ] = szuper ( MetaSingleton , cls ) . __call__ ( * args , ** kwargs ) return cls . _instances [ cls ] osztály MyClass ( metaclass = MetaSingleton ): ...Az alábbiakban a Singleton minta egyik lehetséges megvalósítása a C++ nyelvben ( Myers szinglitonként ismert ), ahol a szingleton egy statikus lokális objektum. A lényeg az, hogy az osztálykonstruktort ként deklarálják private, ami megakadályozza az osztály példányosítását a megvalósításán kívül. Ezen túlmenően a másolatkészítő és a hozzárendelés operátora is magánszemélynek van nyilvánítva. Ez utóbbit deklarálni kell, de nem definiálni, mivel ez könnyen észlelhető linkelési hibát tesz lehetővé, ha véletlenül kódból hívják meg őket. Vegye figyelembe azt is, hogy a fenti példa nem szálbiztos C++03-ban, ha több szálból álló osztállyal szeretne dolgozni, meg kell védenie a változót theSingleInstancea párhuzamos hozzáféréstől, például mutex vagy kritikus szakasz használatával . A C++11 -ben azonban a Myers singleton szálbiztos és zármentes.
Példa C++ nyelven osztály OnlyOne { nyilvános : statikus OnlyOne & Instance () { statikus OnlyOne theSingleInstance ; return theSingleInstance ; } privát : OnlyOne (){} OnlyOne ( const OnlyOne & root ) = törlés ; OnlyOne & operator = ( const OnlyOne & ) = törlés ; };Egy másik példa egy szingli C ++-ban való megvalósítására, öröklési lehetőséggel egy interfész létrehozására, amelynek kerete valójában egy szingli lesz. Egyetlen objektum élettartama kényelmesen szabályozható a referenciaszámláló mechanizmussal .
Példa C++ nyelven osztályú Singleton { védett : statikus Singleton * _self ; Singleton () {} virtuális ~ Singleton () {} nyilvános : statikus Singleton * Példány () { ha ( ! _self ) { _self = új Singleton (); } return _self ; } statikus bool DeleteInstance () { ha ( _self ) { delete_self ; _ _self = 0 ; return true ; } return false ; } }; Singleton * Singleton :: _self = 0 ;A szálbiztos és lusta singleton megvalósításának legegyszerűbb módja azonban a .NET 4-es vagy újabb verzióját igényli.
public pecsétes osztály Singleton { private static readonly Lazy < Singleton > instanceHolder = new Lazy < Singleton >(() => new Singleton ()); privát Singleton () { ... } public static Singleton Instance { get { return instanceHolder . érték ; } } }A Singleton C#-ban való lusta inicializálásához típuskonstruktorok (statikus konstruktor) használata javasolt. A CLR automatikusan meghívja a típus konstruktorát a típus első elérésekor, miközben megőrzi a szálszinkronizálás biztonságát. A típuskonstruktort a fordító automatikusan generálja, és a típus összes mezője (statikus mező) inicializálódik benne. A típuskonstruktort nem szabad kifejezetten beállítani, mert ebben az esetben az közvetlenül a típus meghívása előtt kerül meghívásra, és a JIT fordító nem tudja alkalmazni az optimalizálást (például ha a Singleton első hívása ciklusban történik) .
/// általános Singleton<T> (a szál biztonságos általános osztályt és lusta inicializálást használ) /// <typeparam name="T">Singleton osztály</typeparam> public class Singleton < T > ahol T : class { /// A védett konstruktorra azért van szükség, hogy megakadályozzuk a Singleton osztály példányosítását. /// Az örökölt osztály privát konstruktora hívja meg. védett Singleton () { } /// Egy gyár egy osztálypéldány lusta inicializálására szolgál, privát lezárt class SingletonCreator < S > ahol S : class { //Reflection használja egy nyilvános konstruktor nélküli osztály példányosítására private static only S instance = ( S ) typeof ( S ). GetConstructor ( BindingFlags . Instance | BindingFlags . NonPublic , null , new Type [ 0 ], new ParameterModifier [ 0 ]). Invoke ( null ); public static S CreatorInstance { get { return instance ; } } } public static T Példány { get { return SingletonCreator < T >. CreatorInstance ; } } } /// Singleton public class használata TestClass : Singleton < TestClass > { /// Meghívja a Singleton osztály védett konstruktorát private TestClass () { } public string TestProc () { return "Hello World" ; } }Használhatja a szabványos lusta inicializálási szálbiztos Singleton megvalósítást is:
public class Singleton { /// A védett konstruktorra azért van szükség, hogy megakadályozzuk a Singleton osztály példányának létrehozását Protect Singleton () { } privát lezárt osztály SingletonCreator { private static readonly Singleton példány = new Singleton (); public static Singleton Instance { get { return instance ; } } } public static Singleton Instance { get { return SingletonCreator . Példa ; } } }Ha nincs szükség nyilvános statikus metódusokra vagy tulajdonságokra (a Példány tulajdonságon kívül), akkor egyszerűsített változat is használható:
public class Singleton { private static readonly Singleton példány = new Singleton (); public static Singleton Instance { get { return instance ; } } /// A védett konstruktorra azért van szükség, hogy megakadályozzuk a Singleton osztály védett Singleton példányának létrehozását () { } }Lusta inicializálási példa
névtér Singleton { public class Singleton { private static Singleton példány ; public static Singleton Instance { get { return instance ?? ( példány = new Singleton ()); } } védett Singleton () { } } }Delphi 2005 és újabb verziókhoz a következő példa megfelelő (nem szálbiztos):
Delphi példa type TSingleton = class strict private class var Példány : TSingleton ; public class függvény NewInstance : TObject ; felülbírálni ; vége ; osztályfüggvény TSingleton . _ NewInstance : TObject ; kezdődik , ha nincs hozzárendelve ( példány ) , akkor példány := TSingleton ( öröklött új példány ) ; Eredmény := Példány ; vége ;Korábbi verziók esetén helyezze át az osztálykódot egy külön modulba, és Instancecserélje ki a deklarációt egy globális változó deklarációjára a szakaszában ( implementationa Delphi 7 előtt nem class varvoltak szakaszok strict private).
A Dart dokumentációjából származó gyári kivitelező alapján
class Singleton { static final Singleton _singleton = Singleton . _belső (); factory Singleton () { return _singleton ; } singleton . _belső (); }A szabványos könyvtár (Ruby 1.8 és újabb) tartalmazza a Singleton modult, amely még egyszerűbbé teszi a szinglitonok létrehozását:
szükséges 'singleton' osztály Foo include Singleton end a = Foo . A # Foo.new példány nem érhető el, a Foo osztály (egyetlen) # példányára való hivatkozás megszerzéséhez használja a Foo#instance metódustPrivát óra lehetőség:
package { public class Singleton { private static var _instance : Singleton ; public function Singleton ( privateClass : PrivateClass ) { } public static function getInstance () : Singleton { if ( ! _instance ) _instance = new Singleton ( new PrivateClass ()); return _instance ; } } } // Mivel az osztály ugyanabban a fájlban van deklarálva a // csomagon kívül, csak a Singleton osztály használhatja. class PrivateClass { public function PrivateClass () { } }Kivételi lehetőség megadása:
package { public class Singleton { public static const példány : Singleton = new Singleton (); public function Singleton () { // Boolean(Singleton) hamis, ha az osztály // a statikus konstruktor végrehajtása előtt példányosodik if ( Singleton ) throw new Error ( "Class is singleton." ); } } }Lehetőség hozzáférési változóval:
csomag { public class MySingleton { private static var _instance : MySingleton ; // Elérési változó privát static var _isConstructing : Boolean ; public function MySingleton () { if ( ! _isConstructing ) throw new Error ( "Singleton, használja a MySingleton.instance-ot" ); } public static function példány lekérése () : MySingleton { if ( _instance == null ) { _isConstructing = true ; _instance = új MySingleton (); _isConstructing = false ; } return _példány ; } } }A privát osztály előnyei:
A privát osztály lehetőségének hátránya:
A kivétel lehetőség előnyei:
Klasszikus megközelítés (Coffeescript ≠ 1,5)
class Singleton példány = undefined konstruktor : -> if instance ? vissza példány más példány = @ # Konstruktor kód konzol . assert ( új Singleton az új Singleton );Megközelítés, amely azon a képességen alapul, hogy egy funkciót a testéből lehet elérni (Coffeescript ≠ 1,5)
class Singleton init = -> # konstruktor mint privát osztálymetódus # Konstruktorkód # ... # Cserélje ki a konstruktort, megtartva ezt (@) init = => @ return @ # Igazi kivitelező. Az init # return meghívására szolgál , különben ezt a (@) konstruktort adja vissza: -> return init . alkalmaz ( @ , argumentumok ) konzol . ( az új Singleton az új Singleton ) Megjegyzés: a valódi konstruktor megváltoztatása önmagáról, azaz. konstruktor : -> Singleton = => @ nem ad semmit, mert a kapott JavaScript kódban a konstruktor a helyi Singleton konstruktorra mutat, nem a Singleton osztályra.Ha azonban névtereket használ, akkor ez a lehetőség lehetséges:
ns = {} ns osztály . Singleton konstruktor : -> # Konstruktor kód ns.Singleton == > @ konzol . Assert ( new ns . Singleton is new ns . Singleton )Változók lezárásokkal való elrejtésére épülő módszer. Bónuszként - privát módszerek és tulajdonságok deklarálása, amelyek mind a konstruktor, mind az "osztály" metódusok számára elérhetők lesznek.
const Singleton = ( function () { legyen példány ; // Privát módszerek és tulajdonságok // Konstruktorfüggvény Singleton ( ) { if ( példány ) return példány ; példány = ez ; } // Public Methods Singleton . prototípus . teszt = függvény () {}; return Singleton ; })(); konzol . log ( new Singleton () === new Singleton ());A változó elrejtése nélkül van egy egyszerű megoldás, amely azon alapul, hogy a Singleton függvény egy objektum. A hátránya a példánytulajdonság megváltoztatásának lehetősége az osztályon kívül:
function Singleton () { const instance = Singleton . példány ; if ( példány ) return instance ; singleton . példány = ez ; } singleton . prototípus . teszt = függvény () {}; konzol . log ( new Singleton () === new Singleton ());A legrövidebb lehetőség.
const Singleton = new ( function () { const példány = this ; return function () { return példány ; }; })(); konzol . log ( new Singleton () === new Singleton ());JS osztály statikus privát mezőinek használata:
class Singleton { static # onlyInstance = null ; konstruktor (){ if ( ! Singleton . # onlyInstance ){ Singleton . # onlyInstance = ez ; } else { return Singleton . # onlyInstance ; } } } konzol . log ( new Singleton () === new Singleton ());singleton.h
@interface Singleton : NSObject { } + ( Singleton * ) sharedInstance ; @végesingleton.m
@implementationSingleton _ static Singleton * _sharedInstance = nil ; + ( Singleton * ) sharedInstance { @synchronized ( self ) { if ( ! _sharedInstance ) { _sharedInstance = [[ Singleton alloc ] init ]; } } return _sharedInstance ; } @végeVagy (csak OS X 10.6+, iOS 4.0+ esetén):
@implementationSingleton _ + ( Singleton * ) sharedInstance { static dispatch_once_t pred ; static Singleton * sharedInstance = nil ; dispatch_once ( & pred , ^ { sharedInstance = [[ self alloc ] init ]; }); return sharedInstance ; } @végeTervezési minták | |
---|---|
Fő | |
Generatív | |
Szerkezeti | |
Viselkedési | |
Párhuzamos programozás |
|
építészeti |
|
Java EE sablonok | |
Egyéb sablonok | |
Könyvek | |
Személyiségek |