Søger du en specifik kategori?

 



Oprettet man. d. 09. februar 2009 kl. 12:54

arne_v
arne_v (1.016.094 point)
Guidens karaktér
1
2
3
4
5

Singleton pattern i C#

Denne artikel beskriver Singleton pattern og implementation i C#. Den forudsætter kendskab til C# men ikke til Singleton. Der er en anden artikel med præcis samme indhold bare i VB.NET !
Historie:
V1.0 - 12/01/2004 - original
V1.1 - 31/01/2004 - forbedret formatering
V1.2 - 17/02/2004 - tilføj henvisning til MSDN artikel om lock typeof
V1.3 - 07/03/2004 - tilføj henvisning til VB.NET artikel
V1.4 - 10/05/2005 - ændre til at double locking heller ikke er sikker i .NET
Teori
Singleton pattern løser problemet med at man kun vil
have en enkelt instans af en given klasse.

Singleton pattern er en god objekt orienteret løsning på
samme problem som løses ikke objekt orienteret via en
klasse med kun static members og methods.

Singleton pattern er et såkaldt GoF pattern, hvilket
refererer til bogen "Design Patterns" af Erich Gamma, Richard Helm,
Ralph Johnson og John Vlissides (4 forfattere = Gang Of Four = GoF).

Kendetegnene ved en singleton klasse er:
  - public static metode GetInstance eller property Instance
  - private constructor
(den original GoF kode bruger protected constructor og det kan
man også godt, men min erfaring er at man ikke kan arve fra en
singleton klasse på fornuftig vis)

Eksempel
Her er et standard eksempel på en singleton klasse:

using System;
using System.Collections;

// singleton klasse
public class S1
{
    // normale attributter eksemplificeret ved en ArrayList
    private ArrayList list;
    // den eneste instans der eksisterer
    private static S1 instance = null;
    // private constructor
    private S1() {
        list = new ArrayList();
    }
    // public static metode til at hente instance
    public static S1 GetInstance()
    {
        if(instance == null)
        {
            instance = new S1();
        }
        return instance;
    }
    // normale metoder
    public void Add(object o)
    {
        list.Add(o);
    }
    public ArrayList GetList()
    {
        return list;
    }
}

eller:

using System;
using System.Collections;

// singleton klasse
public class S2
{
    // normale attributter eksemplificeret ved en ArrayList
    private ArrayList list;
    // den eneste instans der eksisterer
    private static S2 instance = new S2();
    // private constructor
    private S2() {
        list = new ArrayList();
    }
    // public static metode til at hente instance
    public static S2 GetInstance()
    {
        return instance;
    }
    // normale metoder
    public void Add(object o)
    {
        list.Add(o);
    }
    public ArrayList GetList()
    {
        return list;
    }
}


C# tillader imidlertid et elegant alternativ med brug af property:

using System;
using System.Collections;

public class S3
{
    // normale attributter eksemplificeret ved en ArrayList
    private ArrayList list;
    // den eneste instans der eksisterer
    private static S3 instance = null;
    // private constructor
    private S3() {
        list = new ArrayList();
    }
    // property til at hente instance
    public static S3 Instance
    {
        get {
            if(instance == null)
            {
                instance = new S3();
            }
            return instance;
        }
    }
    // normale metoder
    public void Add(object o)
    {
        list.Add(o);
    }
    public ArrayList GetList()
    {
        return list;
    }
}


Klassen kan bruges som følger:

using System;
using System.Collections;

class MainClass
{
    public static void Main(string[] args)
    {
        S3 a = S3.Instance;
        a.Add("A");
        S3 b = S3.Instance;
        b.Add("B");
        S3 c = S3.Instance;
        ArrayList list = c.GetList();
        for(int i = 0; i < list.Count; i++)
        {
            Console.WriteLine((string)list[i]);
        }
    }
}


Singleton i multithreaded kontekst
Bemærk at i en multithreaded kontekst bør man kode sin
singleton klasse som:

using System;
using System.Collections;

// singleton klasse
public class S4
{
    // normale attributter eksemplificeret ved en ArrayList
    private ArrayList list;
    // den eneste instans der eksisterer
    private static S4 instance = null;
    // private constructor
    private S4() {
        list = new ArrayList();
    }
    // lock object
    private static object mylock = new object();
    // property til at hente instance
    public static S4 Instance
    {
        get {
            lock(mylock)
            {
                if(instance == null)
                {
                    instance = new S4();
                }
            }
            return instance;
        }
    }
    // normale metoder
    public void Add(object o)
    {
        list.Add(o);
    }
    public ArrayList GetList()
    {
        return list;
    }
}


Vær forsigtig med at bruge:

using System;
using System.Collections;

// singleton klasse
public class S5
{
    // normale attributter eksemplificeret ved en ArrayList
    private ArrayList list;
    // den eneste instans der eksisterer
    private static S5 instance = null;
    // private constructor
    private S5() {
        list = new ArrayList();
    }
    // lock object
    private static object mylock = new object();
    // property til at hente instance
    public static S5 Instance
    {
        get {
            if(instance == null)
            {
                lock(mylock)
                {
                    if(instance == null)
                    {
                        instance = new S5();
                    }
                }
            }
            return instance;
        }
    }
    // normale metoder
    public void Add(object o)
    {
        list.Add(o);
    }
    public ArrayList GetList()
    {
        return list;
    }
}


For selvom det er blevet hævdet af mange inkl. diverse
Microsoft eksempler, at dette trick kendt som double
locing altid virker i .NET, så er fakta at det kun altid virker
på IA-32 og AMD-64 kompatible CPU'er. Problemet kan løses ved
enten at erklære instance field som volatile eller bruge
Thread.MemoryBarrier, men så er en banal lock nok pænere.
Der er dog ikke mange som kører .NET på IA-64 CPU'er
endnu.

I .NET verdenen er det ildeset med brug af lock(typeof(Sx)) og det
bør derfor undgåes (selvom argumentet måske er lidt tyndt) !

For detaljer om dette læs:
  http://blogs.msdn.com/ (...)
  http://blogs.gotdotnet.com/ (...)
  http://discuss.develop.com/ (...)
og:
  http://msdn.microsoft.com/ (...)

Skrevet man. d. 16. februar 2004 kl. 12:23| #1

repsak (19.442 point)
Mange eksempler :-) Ser dog ikke grund til at lave så mange næsten ens, selvom der er en god pointe/linje imellem de forskellige versioner og forbedringer.
Efter min mening mangler dog et argument for den sidste linje :-)

Skrevet fre. d. 07. maj 2004 kl. 17:39| #2

thundergod (17.853 point)
Artiklen lever op til overskriften.
Det er kun anvendelsen af Property, og lock(...) der er ny information.

Skrevet tor. d. 17. juni 2004 kl. 09:47| #3

iakob (19.655 point)
Der er et godt, brugbart og simpelt eksempel på en implementation. Jeg synes artiklen godt kunne have undværet de "uelegante" løsninger (forfatteren har selv en favorit og jeg er enig i hans valg. Der er en enkelt påstand omkring noget man bør undgå, som der ikke er argumenteret for

Skrevet lør. d. 04. december 2004 kl. 17:01| #4

jimgordon (11.349 point)
Perfekt miniartikel. Giver singleton fidusen i fin telegramstil, så man er klar til den tungere litterature omkring dette uundværlige programmeringsdesign.

Skrevet tor. d. 27. juli 2006 kl. 00:43| #5

innercitydk (28.875 point)
Super artikel. Så er der styr på singleton til bunds ;)

Skrevet ons. d. 29. juni 2011 kl. 20:59| #6

impero (12.965 point)
www.excolo.dk
Ved godt dette er en gammel guide, men ville lige give mit input til nye læsere.

Den måde jeg foretrækker at lave singletons i C# er følgende:

class Singleton
{
    private Singleton()
    {       
    }

    public static Singleton Instance
    {
        get
        {
            return Nested.Singleton;
        }
    }

    private class Nested
    {
        static Nested() { }
        internal static readonly Singleton Singleton =
            new Singleton();
    }
}

Denne metode er både thread-safe og lazy, hvilket betyder at den virker i multi-threaded programmer samt at den først opretter singleton objektet når det bliver refereret første gang. Derudover er den super simpel at implementere og kræver ikke brug af locks.

Skrevet man. d. 31. oktober 2011 kl. 00:50| #7

arne_v (1.016.094 point)
re impero)

Den teknik er ret kendt.

Men har du nogen sinde set et eksempel hvor overhead ved den lock er stort nok til at begrunde de ekstra linier kode??

Skriv en kommentar



Mest populære guides i Linux - Generelt

Guidens karakter
!!!Karaktér: 4
5 stemmer
24/02 - 2010
Af: mrmox2

Installation af flash og java-support i din foretrukne browser under linux

Java installeres ikke som standard i din browser under linux, og hvis du vil bruge din egen browser, fx firefox, er flash heller ikke installeret. Det tager kun 5 minutter at gøre det.

Log ind

   

   



   




Tips & Tricks fra PC World

Teaser billede

Top 5: Virale YouTube-videoer fra Danmark

Lægger du mærke til de mere eller mindre skjulte reklamebudskaber, når du ser videoer på nettet? Vi har taget et kig på fem utrolige danske videoer, som er blevet virale hit.


Anmeldelser fra PC World

Teaser billede

Test: Mobil med Ferrari-design - og en Trabant-motor

Motorola har begået endnu en smartphone med lækkert design og potentiale til at være blandt de bedste. Men den når ikke i mål. Se her hvorfor.


Seneste blogindlæg

Teaser billede

Tvangslukke spørgsmål: Hvad er den bedste løsning?

Hej Vi har mange åbne spørgsmål på Eksperten. Vi ville gerne tvangslukke dem - så et spørgsmål efter f.eks. 6 måneder lukkes. Men der er et par uklarheder som ville være gode at få lidt input til:...


Nyheder fra PC World

Teaser billede

Sådan fupper smarte svindlere dig på Facebook

Se hvordan du undgår Facebook-fup i fremtiden.


Nyheder fra Computerworld

Teaser billede

App-udvikling 2.0: Sådan er den perfekte app

ComputerViews: Den værste app-hype er ved at have lagt sig, og nu ser vi konturerne af fremtidens app-design. Men hvordan udnytter man de mobile muligheder optimalt?


Kurser
Samarbejdspartnere

Udgiver · © 2012 IDG Danmark A/S · Hørkær 18 · 2730 Herlev · Tlf.: 77 300 300 · Fax: 77 300 301 · Brug af personoplysninger