C# 单例模式

时间:2025-03-26 07:48:48

目录

一、介绍

二、普通的写法

三、继承的写法

五、静态构造函数的写法

四、Unity中的单例

结束


一、介绍

单例模式是很多程序员学习设计模式的第一个设计模式,主要是平时工作中会用到,另一个在23个设计模式中算比较简单一个,从字面意思上理解为一个类只有一个实例,并对外开放一个静态的访问属性,所以一般称之为单例模式。

在各种单例模式版本中,总结又以下共同点:
1.唯一的、私有的且无参的构造函数,这样不允许外部类进行实例化;
2.类是密封的,尽管这不是强制的,但是严格来讲从上一点来看密封类能有助于JIT的优化;
3.一个静态变量应该指向类的唯一实例;
4.一个公共的静态变量用于获得这个类的唯一实例(如果需要,应该创建它;

在设计模式六大原则中的 单一职责原则和开闭原则 的作用是要求对代码做一定的分类和约束,所以我不建议过多的使用单例模式,除非用在常用的一些公共管理类中,比如游戏开发中的 ,UIManager,另外是工具类,专门用来写一些算法的类,但是这种工具类直接用静态类,静态方法就可以了,用单例模式去调用会感觉非常的别扭。

二、普通的写法

将访问入口直接写在类的内部,并将类的构造函数设为私有,防止其他类进行实例化,并对外开放一个访问的入口,这个是网上很多帖子介绍单例常用的写法。

using System;

namespace 单例模式
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ();

            ();
        }
    }
}

public class Monkey
{
    private static Monkey instance = null;
    public static Monkey Instance 
    { 
        get
        {
            if(instance == null)
                instance = new Monkey();
            return instance;
        } 
    }

    public void Robbery()
    {
        ("抢你的食物");
    }

    private Monkey() { }
}

三、继承的写法

继承的写法就是专门写一个单例类,其他类如果想用单例模式直接继承就好了,同时缺点也出来了,那就是无法继承其他类了

using System;

namespace 单例模式
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ();

            ();
        }
    }
}

public class Monkey : Singleton<Monkey>
{
    public void Robbery()
    {
        ("抢你的食物");
    }
}

public abstract class Singleton<T> where T : new()
{
    private static T _instance;
    private static object mutex = new object();
    public static T Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (mutex)
                {
                    if (_instance == null)
                    {
                        _instance = new T();
                    }
                }
            }
            return _instance;
        }
    }
}

五、静态构造函数的写法

使用静态构造函数去实例化单例,同样也符合单例的特征,在使用上和其他的单例并不会有什么不同,相反还会更加的简洁优雅。

using System;

namespace 单例模式
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ();

            ();
        }
    }
}

public class Monkey
{
    public static Monkey Instance = null;

    public void Robbery()
    {
        ("抢你的食物");
    }

    static Monkey()
    {
        Instance = new Monkey();
    }

    private Monkey() { }
}

四、Unity中的单例

下面代码可以作为参考,如果继承了这个单例类,在调用时会自动实例化一个游戏物体,会跟随着场景移动,并防止在移动到其他场景时,又实例化出一个相同的游戏物体。

public class UnitySingleton<T> : MonoBehaviour where T : Component {
    private static T _instance = null;
    public static T Instance {
        get {
            if (_instance == null) {
                _instance = FindObjectOfType(typeof(T)) as T;
                if (_instance == null) {
                    GameObject obj = new GameObject();
                    _instance = (T)(typeof(T));
                     = ;
                    //  = ;
                     = typeof(T).Name;
                }
            }
            return _instance;
        }
    }

    public virtual void Awake() {
        DontDestroyOnLoad();
        if (_instance == null) {
            _instance = this as T;
        }
        else {
            ();
        }
    }
}

DontDestroyOnLoad 方法的使用,也可以使用下面代码

using UnityEngine;

public class GameManager : MonoBehaviour {

    public static GameManager Instance;
    private static bool origional = true;

    private void Awake()
    {
        if (origional)
        {
            Instance = this as GameManager;
            origional = false;
            DontDestroyOnLoad();
        }
        else
        {
            Destroy();
        }
    }
}

在 GameManager 中如果还要添加其他的管理类,在 Start 方法中使用 AddComponent 方法添加就好了。

结束

如果这个帖子对你有所帮助,欢迎 关注 + 点赞 + 留言

end