Egyke programtervezési minta
Az egyke programtervezési minta olyan programtervezési minta, amely egyetlen objektumra korlátozza egy osztály létrehozható példányainak számát.
![](http://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Singleton_UML_class_diagram.svg/220px-Singleton_UML_class_diagram.svg.png)
Gyakori, hogy egy osztályt úgy kell megírni, hogy csak egy példány legyen belőle. Ehhez jól kell ismerni az objektumorientált programozás alapelveit. Az osztályból példányt a konstruktorával lehet készíteni. Ha van publikus konstruktor az osztályban, akkor akárhány példány készíthető belőle, tehát publikus konstruktora nem lehet az egykének. De ha nincs konstruktor, akkor nem hozható létre a példány, amin keresztül hívhatnánk a metódusait. A megoldást az osztályszintű (statikus) metódusok jelentik. Ezeket akkor is lehet hívni, ha nincs példány. Az egykének tehát van egy osztályszintű metódusa (szerezPéldány, angolul getInstance), ami minden hívójának ugyanazt a példányt adja vissza. Természetesen ezt a példányt is létre kell hozni, ehhez privát konstruktort kell készíteni, amit a szerezPéldány az egyke osztály tagjaként meghívhat.[1]
Sokan erősen kritizálják az egyke mintát, és antimintának tekintik, mivel szükségtelen korlátozásokat és globális állapotokat helyez el az alkalmazásban, illetve csökkenti a tesztelhetőséget.[2][3][4]
Felhasználása
szerkesztésEgykét csak akkor érdemes használni, ha több példány egyidejű létezése a rendszer rendellenes működését vagy összeomlását okozhatja. A homlokzatok például gyakran egykék. Az absztrakt gyártó, az építő és a prototípus minták implementációja is gyakran épül az egyke mintára.
A globális változókkal szemben gyakran az egykéket részesítik előnyben, mivel nem szennyezik a névteret szükségtelen változókkal, és lehetővé teszik a lusta allokációt és inicializációt, míg a globális változók mindig fogyasztanak erőforrásokat.
Megvalósítása
szerkesztésA megvalósításnak biztosítania kell, hogy:
- mindig egyetlen objektum létezzen
- mindig legyen globális hozzáférés a példányhoz
Ezt rendszerint így érik el:
- minden konstruktor privát
- a példány referenciája egy osztálymetóduson keresztül érhető el
A példányt rendszerint privát osztálypéldányként tárolják. A példány a változó inicializálásával jön létre, valamivel azelőtt, hogy az osztálymetódust meghívják. Egyszerű példa Java nyelven:
public final class Egyke {
private static final Egyke PELDANY = new Egyke();
private Egyke() {}
public static Egyke aPeldany() {
return PELDANY;
}
}
Javában gyakran használnak egyelemű enum-ot is, mert így maga a Java környezet biztosítja a példány egyediségét:
public enum Egyke {
PELDANY {
// ...
}
}
Az egyke használható lusta inicializációval. Ekkor a példány csak akkor jön létre, amikor az osztálymetódus először meghívódik. Ha ezt párhuzamos környezetben használják, akkor biztosítani kell, hogy ne legyen versenyhelyzet, különben több szál is létrehozhat egy-egy példányt. Ehhez teljes szinkronizálás helyett (a teljesítmény növelése céljából) gyakran használnak duplán ellenőrzött lockolást, ami azonban önmagában elégtelen, mivel az ellenőrzés pillanatában a példány inicializációja még bejezetlen lehet, annak ellenére, hogy a változó értéke már nem null
.[5] A következő Java példa egy segédváltozót használ az inicializált állapot ellenőrzésére:
public final class Egyke {
private static volatile boolean letrehozva = false;
private static volatile Egyke peldany = null;
private Egyke() {}
public static Egyke aPeldany() {
if (!letrehozva) {
synchronized(Egyke.class) {
if (!letrehozva) {
peldany = new Egyke();
letrehozva = true;
}
}
}
return peldany;
}
}
Egyszerű egyke példakód C#-ban
szerkesztésusing System;
namespace EgykeFonalBiztos
{
public sealed class Egyke
{
// A statikus konstruktor akkor fut le, amikor az osztályt példányosítjuk,
// vagy statikus tagra hivatkozunk ÉS egy Application Domain alatt
// (értsd: adott program futásakor) maximum egyszer futhat le.
private static readonly Egyke egyed = new Egyke();
// privát konstruktor külső 'new' példányosítás ellen
private Egyke() {}
// statikus konstruktor
// Azon osztályok, melyek nem rendelkeznek statikus 101
// konstruktorral beforefieldinit attribútumot
// kapnak az IL kódban. A statikus tagok inicializációja
// a program kezdetén azonnal megtörténik.
// Az olyan osztályok, amelyeknek van statikus konstruktora
// ezt nem kapják meg,
// ezért a statikus tagok akkor példányosulnak,
// amikor először hivatkozunk az osztályra,
// vagyis jelen esetben amikor elkérjük a példányt.
static Egyke() {}
public static Egyke Peldany
{
get
{
return egyed;
}
}
}
class Program
{
static void Main(string[] args)
{
Egyke s1 = Egyke.Peldany;
Egyke s2 = Egyke.Peldany;
if (s1 == s2)
Console.WriteLine("OK");
Console.ReadKey();
}
}
}
Jegyzetek
szerkesztés- ↑ http://aries.ektf.hu/~hz/pdf-tamop/pdf-xx/ProgTechJegyzet.1.1.6.pdf
- ↑ Scott Densmore. Why singletons are evil, May 2004
- ↑ Steve Yegge. Singletons considered stupid, September 2004
- ↑ Clean Code Talks - Global State and Singletons
- ↑ The "Double-Checked Locking is Broken" Declaration. (Hozzáférés: 2021. augusztus 25.)
Fordítás
szerkesztésEz a szócikk részben vagy egészben a Singleton pattern című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.