Apa itu singleton dalam C #?


182

Apa itu Singleton dan kapan saya harus menggunakannya?



4
Juga, Singleton adalah salah satu pola desain yang paling banyak digunakan dan disalahgunakan dalam pemrograman OO.
ChaosPandion

3
@ Fabiano: Karena memiliki cara membuat kopling yang tidak masuk akal (bagaimana saya bisa Xberbicara dengan Y? Buat saja Ysingleton!), Yang pada gilirannya mengarah pada kesulitan pengujian / debugging dan gaya pemrograman prosedural. Terkadang lajang diperlukan; sebagian besar waktu, tidak.
Aaronaught

3
Ini adalah salah satu pertanyaan wawancara telepon standar saya. Jawaban yang benar adalah: tidak pernah.
Jonnii

3
@jonnii itu bagus, ini membantu memperingatkan calon pengembang seperti apa bosnya!
Tn. Boy

Jawaban:


145

Singleton adalah kelas yang hanya memungkinkan satu instance dari dirinya sendiri dibuat - dan memberikan akses yang sederhana dan mudah ke instance tersebut. Premis tunggal adalah pola di seluruh pengembangan perangkat lunak.

Ada implementasi C # "Menerapkan Pola Singleton dalam C #" yang mencakup sebagian besar dari apa yang perlu Anda ketahui - termasuk beberapa saran bagus tentang keamanan utas .

Sejujurnya, sangat jarang Anda perlu menerapkan singleton - menurut saya itu harus menjadi salah satu hal yang harus Anda sadari, bahkan jika itu tidak digunakan terlalu sering.


2
tutorial yang bagus tapi
sial

Berikut ini tautan yang lebih langsung ke apa yang saya anggap sebagai implementasi yang ideal pada tahun 2020. Yaitu, " menggunakan jenis .Tezy <T> malas .NET 4 ," serta tautan ke Microsoft Doc untuk Lazy<T> Class.
Chiramisu

52

Anda meminta C #. Contoh sepele:


public class Singleton
{
    private Singleton()
    {
        // Prevent outside instantiation
    }

    private static readonly Singleton _singleton = new Singleton();

    public static Singleton GetSingleton()
    {
        return _singleton;
    }
}

14
bukan utas yang aman. Dua utas dapat memanggil waktu yang sama dan dapat membuat dua objek terpisah.
Alagesan Palani

5
@Alagesan Palani, memang Anda benar. Saya tidak mahir dalam detail level rendah dari inisialisasi tingkat kelas, tapi saya pikir perubahan yang saya buat membahas masalah aman-thread.
Chris Simmons

3
tentu, saya TIDAK menunjuk Anda salah. saya memberikan petunjuk kepada pembaca tentang keamanan utas, sehingga mereka akan berhati-hati jika mereka harus menghadapinya.
Alagesan Palani

9
Tidak, saya pikir komentar Anda penting. Mengingat bahwa seorang singleton seharusnya memberikan satu - dan hanya satu - contoh, kondisi balapan di sini membuka kemungkinan lebih dari satu dikirimkan. Lihat versi sekarang, dengan inisialisasi bidang statis. Saya percaya ini memperbaiki masalah keamanan thread, jika saya membaca dokumen dan SO ini menjawab dengan benar.
Chris Simmons

1
@AlagesanPalani, saya melihat bahwa Anda telah menyatakan bahwa beberapa jawaban lainnya tidak aman utas. Apakah Anda ingin memberikan solusi yang aman untuk thread?
Bonez024

39

Apa itu: Kelas yang hanya memiliki satu, contoh persisten sepanjang masa aplikasi. Lihat Pola Singleton .

Kapan Anda harus menggunakannya: sesedikit mungkin. Hanya ketika Anda benar-benar yakin bahwa Anda membutuhkannya. Saya enggan mengatakan "tidak pernah", tetapi biasanya ada alternatif yang lebih baik, seperti Injeksi Ketergantungan atau hanya kelas statis.


16
Saya tidak yakin bahwa kelas statis adalah alternatif yang lebih baik daripada lajang ... itu benar-benar tergantung pada situasi dan bahasa.
marcgg

5
Kelas statis tidak berperilaku dengan cara yang sama seperti singleton, singleton dapat diteruskan ke metode sebagai parameter sedangkan kelas statis tidak bisa.
TabbyCool

4
Setuju dengan marcgg - Saya tidak melihat kelas statis sebagai alternatif yang baik untuk lajang, karena Anda masih memiliki masalah dalam memasok pengganti, misalnya selama pengujian komponen yang tergantung pada kelas ini. Tapi saya juga melihat kegunaan yang berbeda, kelas statis biasanya akan digunakan untuk fungsi utilitas independen yang tidak bergantung pada negara, di mana singleton adalah instance kelas aktual, dan biasanya akan menyimpan keadaan. Saya sepenuhnya setuju untuk menggunakan DI sebagai gantinya, dan kemudian memberitahu wadah DI Anda bahwa Anda ingin hanya menggunakan satu instance dari kelas itu.
Pete

9
Saya menurunkan jawaban ini karena tidak memberi saya informasi kapan saya akan menggunakannya. "Hanya ketika Anda membutuhkannya" tidak benar-benar memberi saya informasi sama sekali untuk seseorang yang baru mengenal lajang.
Sergio Tapia

9
@Adkins: DI adalah singkatan dari Dependency Injection, yang mana setiap dependensi kelas dilewatkan melalui (biasanya) konstruktor atau properti publik. DI saja tidak menyelesaikan masalah "jarak", tetapi biasanya dijalankan bersamaan dengan wadah Inversion-of-Control (IoC) yang tahu cara menginisialisasi dependensi secara otomatis. Jadi, jika Anda membuat Singleton untuk menyelesaikan masalah "X tidak tahu bagaimana menemukan / berbicara dengan Y", kombinasi DI dan IoC dapat memecahkan masalah yang sama dengan kopling yang lebih longgar.
Aaronaught

27

cara lain untuk mengimplementasikan singleton dalam c #, saya pribadi lebih suka cara ini karena Anda dapat mengakses instance dari kelas singeton sebagai properti alih-alih metode.

public class Singleton
    {
        private static Singleton instance;

        private Singleton() { }

        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                    instance = new Singleton();
                return instance;
            }
        }

        //instance methods
    }

tapi yah, sejauh yang saya tahu kedua cara dianggap 'benar' jadi itu hanya masalah selera pribadi.


11
bukan utas yang aman. Dua utas dapat memanggil waktu yang sama dan dapat membuat dua objek terpisah.
Alagesan Palani

11
using System;
using System.Collections.Generic;
class MainApp
{
    static void Main()
    {
        LoadBalancer oldbalancer = null;
        for (int i = 0; i < 15; i++)
        {
            LoadBalancer balancerNew = LoadBalancer.GetLoadBalancer();

            if (oldbalancer == balancerNew && oldbalancer != null)
            {
                Console.WriteLine("{0} SameInstance {1}", oldbalancer.Server, balancerNew.Server);
            }
            oldbalancer = balancerNew;
        }
        Console.ReadKey();
    }
}

class LoadBalancer
{
    private static LoadBalancer _instance;
    private List<string> _servers = new List<string>();
    private Random _random = new Random();

    private static object syncLock = new object();

    private LoadBalancer()
    {
        _servers.Add("ServerI");
        _servers.Add("ServerII");
        _servers.Add("ServerIII");
        _servers.Add("ServerIV");
        _servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
        if (_instance == null)
        {
            lock (syncLock)
            {
                if (_instance == null)
                {
                    _instance = new LoadBalancer();
                }
            }
        }

        return _instance;
    }

    public string Server
    {
        get
        {
            int r = _random.Next(_servers.Count);
            return _servers[r].ToString();
        }
    }
}

Saya mengambil kode dari dofactory.com , tidak ada yang mewah tapi saya menemukan ini jauh lebih baik daripada contoh dengan Foo and Bar dan buku dari Judith Bishop di C # 3.0 Design Patterns memiliki contoh tentang aplikasi aktif di mac dock.

Jika Anda melihat kode kita sebenarnya membangun objek baru untuk loop, sehingga menciptakan objek baru tetapi menggunakan kembali contoh sebagai akibat dari mana oldbalancer dan newbalancer memiliki instance yang sama, Bagaimana? itu karena kata kunci statis yang digunakan pada fungsi GetLoadBalancer () , meskipun memiliki nilai server yang berbeda yang merupakan daftar acak, statis pada GetLoadBalancer () milik tipe itu sendiri dan bukan ke objek tertentu.

Selain itu ada penguncian cek ganda di sini

if (_instance == null)
            {
                lock (syncLock)
                {
                    if (_instance == null)

sejak dari MSDN

Kata kunci kunci memastikan bahwa satu utas tidak memasukkan bagian kode yang penting saat utas lainnya ada di bagian kritis. Jika utas lain mencoba memasukkan kode yang dikunci, ia akan menunggu, memblokir, hingga objek dilepaskan.

jadi setiap kali saling pengecualian kunci dikeluarkan, bahkan jika itu tidak perlu yang tidak perlu, jadi kami memiliki cek nol.

Semoga ini membantu dalam membersihkan lebih banyak.

Dan tolong beri komentar jika pemahaman saya mengarahkan cara yang salah.


6

Singleton (dan ini tidak terkait dengan C #, ini adalah pola desain OO) adalah ketika Anda ingin memperbolehkan SATU instance kelas dibuat di seluruh aplikasi Anda. Penggunaan biasanya akan mencakup sumber daya global, meskipun saya akan mengatakan dari pengalaman pribadi, mereka sangat sering menjadi sumber rasa sakit yang hebat.


5

Meskipun hanya ada satu instance dari singleton, itu tidak sama dengan kelas statis. Kelas statis hanya dapat berisi metode statis dan tidak pernah dapat dipakai, sedangkan instance dari singleton dapat digunakan dengan cara yang sama seperti objek lainnya.


2

Ini adalah pola desain dan tidak spesifik untuk c #. Lebih banyak tentang itu di internet dan SO, seperti pada artikel wikipedia ini .

Dalam rekayasa perangkat lunak, pola singleton adalah pola desain yang digunakan untuk membatasi instantiasi kelas ke satu objek. Ini berguna ketika tepat satu objek diperlukan untuk mengoordinasikan tindakan di seluruh sistem. Konsep ini kadang-kadang digeneralisasikan ke sistem yang beroperasi lebih efisien ketika hanya ada satu objek, atau yang membatasi instantiasi ke sejumlah objek (katakanlah, lima). Beberapa menganggapnya sebagai anti-pola, menilai bahwa itu terlalu sering digunakan, memperkenalkan batasan yang tidak perlu dalam situasi di mana satu-satunya contoh kelas tidak benar-benar diperlukan, dan memperkenalkan negara global ke dalam suatu aplikasi.

Anda harus menggunakannya jika Anda menginginkan kelas yang hanya dapat di-instanciated satu kali.


2

Saya menggunakannya untuk data pencarian. Muat sekali dari DB.

public sealed class APILookup
    {
        private static readonly APILookup _instance = new APILookup();
        private Dictionary<string, int> _lookup;

        private APILookup()
        {
            try
            {
                _lookup = Utility.GetLookup();
            }
            catch { }
        }

        static APILookup()
        {            
        }

        public static APILookup Instance
        {
            get
            {
                return _instance;
            }
        }
        public Dictionary<string, int> GetLookup()
        {
            return _lookup;
        }

    }

2

Apa itu singleton:
Ini adalah kelas yang hanya memungkinkan satu instance dari dirinya sendiri dibuat, dan biasanya memberikan akses sederhana ke instance itu.

Kapan sebaiknya Anda gunakan:
Itu tergantung situasi.

Catatan: tolong jangan gunakan pada koneksi db, untuk jawaban terperinci silakan lihat jawaban @Chad Grant

Berikut adalah contoh sederhana dari Singleton:

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

Anda juga dapat menggunakan Lazy<T>untuk membuat Singleton.

Lihat di sini untuk contoh lebih rinci menggunakanLazy<T>


1

Inilah singleton itu: http://en.wikipedia.org/wiki/Singleton_pattern

Saya tidak tahu C #, tetapi sebenarnya hal yang sama di semua bahasa, hanya implementasi yang berbeda.

Anda harus menghindari singleton jika memungkinkan, tetapi dalam beberapa situasi itu sangat nyaman.

Maaf untuk bahasa Inggris saya;)


Bahasa Inggris Anda baik-baik saja :)
FrenkyB

1

Kelas singleton digunakan untuk membuat satu instance untuk seluruh domain aplikasi.

public class Singleton
{
    private static Singleton singletonInstance = CreateSingleton();

    private Singleton()
    {
    }

    private static Singleton CreateSingleton()
    {
        if (singletonInstance == null)
        {
            singletonInstance = new Singleton();
        }

        return singletonInstance;
    }

    public static Singleton Instance
    {
        get { return singletonInstance; }            
    }
}

Dalam artikel ini dijelaskan bagaimana kita dapat membuat kelas singleton thread aman menggunakan variabel readonly dan penggunaan praktisnya dalam aplikasi.


1

Saya tahu sudah terlambat untuk menjawab pertanyaan, tetapi dengan Properti Otomatis Anda dapat melakukan sesuatu seperti itu:

public static Singleton Instance { get; } = new Singleton();

Di mana SingletonAnda kelas dan dapat melalui, dalam hal ini adalah properti readonly Instance.


0

EX Anda dapat menggunakan Singleton untuk informasi global yang perlu disuntikkan.

Dalam kasus saya, saya menyimpan detail pengguna yang Dicatat (nama pengguna, izin, dll.) Di Kelas Statis Global. Dan ketika saya mencoba mengimplementasikan Tes Unit, tidak ada cara saya bisa menyuntikkan dependensi ke dalam kelas Controller. Jadi saya telah mengubah kelas Statis saya ke pola Singleton.

public class SysManager
{
    private static readonly SysManager_instance = new SysManager();

    static SysManager() {}

    private SysManager(){}

    public static SysManager Instance
    {
        get {return _instance;}
    }
}

http://csharpindepth.com/Articles/General/Singleton.aspx#cctor


0

Kita perlu menggunakan Pola Desain Singleton di C # ketika kita perlu memastikan bahwa hanya satu instance dari kelas tertentu yang akan dibuat dan kemudian menyediakan akses global sederhana ke instance itu untuk seluruh aplikasi.

Skenario real-time di mana Anda dapat menggunakan Pola Desain Singleton: Proxy Layanan: Seperti yang kita ketahui menggunakan API Layanan adalah operasi yang luas dalam aplikasi. Proses yang menghabiskan sebagian besar waktu adalah membuat klien Layanan untuk memohon API layanan. Jika Anda membuat proxy Layanan sebagai Singleton maka itu akan meningkatkan kinerja aplikasi Anda.

Fasad: Anda juga dapat membuat koneksi Database sebagai Singleton yang dapat meningkatkan kinerja aplikasi.

Log: Dalam aplikasi, melakukan operasi I / O pada file adalah operasi yang mahal. Jika Anda membuat Logger sebagai Singleton maka itu akan meningkatkan kinerja operasi I / O.

Berbagi data: Jika Anda memiliki nilai konstan atau nilai konfigurasi maka Anda dapat menyimpan nilai-nilai ini di Singleton sehingga ini dapat dibaca oleh komponen lain dari aplikasi.

Caching: Seperti yang kita ketahui, mengambil data dari database adalah proses yang menghabiskan waktu. Dalam aplikasi Anda, Anda dapat men-cache master dan konfigurasi dalam memori yang akan menghindari panggilan DB. Dalam situasi seperti itu, kelas Singleton dapat digunakan untuk menangani caching dengan sinkronisasi utas secara efisien yang secara drastis meningkatkan kinerja aplikasi.

Kerugian dari Pola Desain Singleton di C # Kerugian menggunakan Pola Desain Singleton di C # adalah sebagai berikut:

Unit testing sangat sulit karena memperkenalkan negara global ke dalam suatu aplikasi. Ini mengurangi potensi paralelisme dalam suatu program karena untuk mengakses instance tunggal dalam lingkungan multi-utas, Anda perlu membuat serialisasi objek dengan menggunakan penguncian.

Saya telah mengambil ini dari artikel berikut.

https://dotnettutorials.net/lesson/singleton-design-pattern/


0

Thread Safe Singleton tanpa menggunakan kunci dan tanpa instantiasi malas.

Implementasi ini memiliki konstruktor statis, sehingga hanya dijalankan sekali per Domain Aplikasi.

public sealed class Singleton
{

    static Singleton(){}

    private Singleton(){}

    public static Singleton Instance { get; } = new Singleton();

}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.