首页 > 其他分享 >设计模式(一)单例

设计模式(一)单例

时间:2023-08-08 15:13:16浏览次数:47  
标签:private instance 实例 static 单例 new 设计模式 public

一、定义

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种创建型模式。

  • 在单例类的内部定义了一个静态对象,作为提供外部共享的唯一实例
  • 为了防止在外部对单例类实例化,它的构造函数被设为private
  • 在单例类提供一个静态方法或者静态变量(本文均用方法获取实例),让客户可以访问它的唯一实例

二、分类

1、饿汉

由于在C#中调用静态构造函数的时机不是由程序员掌控的,而是当.NET运行时发现第一次使用该类型的时候自动调用该类型的静态构造函数,这样会过早地创建实例,从而降低内存的使用效率。

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

    private Singleton1()
    {

    }

    public static Singleton1 GetInstance()
    {
        return instance;
    }
}

2、懒汉

懒汉式也被称为延迟加载,但是多线程下不安全,可能创建多个实例。

public class Singleton2
{
    private static Singleton2 instance = null;

    private Singleton2()
    {

    }
    public static Singleton2 GetInstance()
    {
        if (instance == null)
        {
            instance = new Singleton2();
        }
        return instance;
    }
}

3、双检锁 Double-Checked Locking

在懒汉式的基础上增加双重检验和锁,但是控制繁琐,影响性能。

public class Singleton3
{
    private static Singleton3 instance = null;
    private static readonly object syncLocker = new object();
    private Singleton3()
    {

    }

    public static Singleton3 GetInstance()
    {
        if (instance == null)
        {
            lock (syncLocker)
            {
                if (instance == null)
                {
                    instance = new Singleton3();
                }
            }
        }
        return instance;
    }
}

很多面试提问会涉及到“锁、多线程”以及线程安全的问题,整点链接以供学习。
https://www.cnblogs.com/MingsonZheng/p/12547288.html
https://www.cnblogs.com/zhao987/p/12551815.html
https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.concurrent?view=net-6.0

4、静态内部类

既可以实现延迟加载,又可以保证线程安全,不影响系统性能,但其有一些面向对象的编程语言并不支持此种方式。

public class Singleton4
{
    private Singleton4()
    {

    }

    public static Singleton4 GetInstance()
    {
        return Nested.instance;
    }

    private class Nested
    {
        static Nested() { }
        internal static readonly Singleton4 instance = new Singleton4();
    }
}
5、Lazy

.NET 4或其以上版本,可以使用System.Lazy type来实现完全懒汉式,代码简洁且性能好。

public class Singleton5
{
    private static readonly Lazy<Singleton5> lazy = new Lazy<Singleton5>(() => new Singleton5());
    private Singleton5() { }
    public static Singleton5 GetInstance()
    {
        return lazy.Value;
    }
}

Lazy文档

6、CAS

Interlocked类,为多个线程共享的变量提供原子操作。

public class Singleton6
{
    private static Singleton6 instance = null;
    private Singleton6() { }
    public static Singleton6 GetInstance()
    {
        if (instance != null)
        {
            return instance;
        }
        var instance_value = new Singleton6();
        Interlocked.CompareExchange(ref instance, instance_value, null);
        return instance;
    }
}

Interlocked.CompareExchange文档

三、测试

单线程都是没有问题的,主要是要注意,多线程下线程安全的问题,举个例子,测试如下:

Console.WriteLine("以5.Lazy为例简单测试");
Singleton5 singleton5_1 = Singleton5.GetInstance();
Singleton5 singleton5_2 = Singleton5.GetInstance();
if (singleton5_1 == singleton5_2)
{
    Console.WriteLine("实例唯一\n");
}

Console.WriteLine("以2.懒汉为例多线程不安全测试");
List<Task> singleton2Tasks = new List<Task>();
ConcurrentBag<Singleton2> singleton2List = new ConcurrentBag<Singleton2>();
for (int i = 0; i < 100; i++)
{
    singleton2Tasks.Add(Task.Run(() =>
    {
        singleton2List.Add(Singleton2.GetInstance());
    }));
}
Task.WaitAll(singleton2Tasks.ToArray());
int dis2Count = singleton2List.Distinct().Count();
Console.WriteLine($"实例总个数:{singleton2List.Count},去重后个数:{dis2Count},多线程实例{(dis2Count > 1 ? "不" : "")}唯一\n");

Console.WriteLine("以5.懒汉为例多线程安全测试");
List<Task> singleton5Tasks = new List<Task>();
ConcurrentBag<Singleton5> singleton5List = new ConcurrentBag<Singleton5>();
for (int k = 0; k < 100; k++)
{
    singleton5Tasks.Add(Task.Run(() =>
    {
        singleton5List.Add(Singleton5.GetInstance());
    }));
}
Task.WaitAll(singleton5Tasks.ToArray());
int dis5Count = singleton5List.Distinct().Count();
Console.WriteLine($"实例总个数:{singleton5List.Count},去重后个数:{singleton5List.Distinct().Count()},多线程实例{(dis5Count > 1 ? "不" : "")}唯一");

Console.ReadLine();

四、前人栽树,后人乘凉

https://cloud.tencent.com/developer/article/1781261
https://www.cnblogs.com/flame7/archive/2020/09/26/13734605.html
https://www.cnblogs.com/edisonchou/p/6618503.html
https://blog.csdn.net/ni996570734/article/details/122958079

标签:private,instance,实例,static,单例,new,设计模式,public
From: https://www.cnblogs.com/WinterSir/p/16643061.html

相关文章

  • Python单例模式
    ##py_singleton.py#py_learn##CreatedbyZ.Steveon2023/8/809:45.###查看对象地址demo#classUtility:#pass###u1=Utility()#u2=Utility()###输出发现u1、u2两个对象的地址不一样#print(u1)#print(id(u1))#print(u2)#......
  • Java设计模式的七大基本原则
    设计模式是为了让程序(软件)具有更好的代码重用性,可读性,可扩展性,可靠性,使程序呈现高内聚,低耦合的特性设计模式的原则其实就收是程序员在编写时,应当遵守的原则,也是各种模式的基础(Java设计模式的七大基本原则)一、单一职责原则<A>对类来说的,即一个类应只负责一项职责,如果A负责......
  • 【Java设计模式004】建造者模式
    大家好,个人gzh是大猪和小猪的小家,我们的gzh是朝阳三只大明白,满满全是干货,分享近期的学习知识以及个人总结(包括读研和IT),跪求一波关注,希望和大家一起努力、进步!!概述首先来看一个例子,假设我们需要建造一个房子,那么必须建造墙、屋顶、地板、门…如果还需要游泳池、健身室,那么该怎么办呢......
  • 实现单例模式的5种方式
    参考链接......
  • 一个类继承一个单例还是单例的实现
    classA{static$inc;privatefunction__construct(){}privatefunction__clone(){}publicstaticfunctionget_self(){if(!(self::$incinstanceofself)){self::$inc=newself();}returnself::$inc;}......
  • Unity___设计模式总结
    模板模式子类可以继承父类的方法单例模式饿汉式游戏一开始就加载privatestaticTinstance=newT();懒汉式策略模式可以参考Sort()函数或者说回调函数在使用sort()函数时,当系统无法自动排序时需要传递一个比较类或者比较函数给方法;观察者模式(事件中心)事件源(......
  • 单例模式
    **介绍:**确保一个类只有一个实例,并提供一个全局访问点。**主要解决:**一个全局使用的类频繁地创建与销毁。**何时使用:**当您想控制实例数目,节省系统资源的时候。**如何解决:**判断系统是否已经有这个单例,如果有则返回,如果没有则创建。**关键代码:**构造函数是私有的。应用实例:1......
  • 基于C#的应用程序单例唯一运行的完美解决方案 - 开源研究系列文章
    今次介绍一个应用程序单例唯一运行方案的代码。我们知道,有些应用程序在操作系统中需要单例唯一运行,因为程序多开的话会对程序运行效果有影响,最基本的例子就是打印机,只能运行一个实例。这里将笔者单例运行的代码共享出来,需要的读者请自己复用该代码到自己的项目中即可。......
  • 4 抽象工厂方法 -- go语言设计模式
    工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。因此,可以考虑将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产,这就是本文将要学习的......
  • 设计模式-纯文字描述
    设计模式在很多面试题中经常出现,同时,在写大型项目中,设计模式可以让代码更简洁,架构更合理,所以是我们必须要掌握的。 1、观察者模式观察者模式是一种行为设计模式,允许你定义一种订阅机制,可在对象事件发生时通知多个“观察”该对象的其他对象。一般需要以下几步:1、定义多个......