[Design pattern] Singleton pattern realization in Unity

Preface

    The design pattern is the best solution to some general problems that many developers have summed up in the long-term development process.
    The singleton pattern is one of the simplest and most commonly used. It is aimed at The problem is that frequent creation and destruction of reused global objects wastes system resources. Therefore, it is suitable for situations where you want to reasonably control the number of instantiations to save system resources. It has the following characteristics:

1. Only one instance of a singleton class can be created;

2. The instance of the singleton class is created by itself rather than through the outside world;

3. The singleton class must provide this instance to external objects

The above reference is from the rookie tutorial: singleton mode



Implementation

    The singleton mode in Unity can be roughly divided into two categories :
inheriting the MonoBehaviour class and not inheriting the MonoBehaviour class .


Inherit the realization of MonoBehaviour class

    The way that MonoBehaviour subclasses implement the singleton mode is very simple, just create a static instance and add the instance = this. The code is as follows:

public class Singleton : MonoBehaviour
{
    
    
    public static Singleton instance;	//创建静态实例
	
	//防止外部进行额外的实例化将构造函数设为private
    private Singleton()
    {
    
     
        
    }

    void Awake()
    {
    
    
        instance = this;
    }

}

    The privatization of the constructor can prevent additional instantiation from outside:

Prevent instantiation



Does not inherit the implementation of MonoBehaviour class

    Not inherit MonoBehaviour class implementation is slightly more complicated, but also applies to many different situations implementations, such as: a hungry man style, lazy type, static inner classes, thread-safe lazy, double check locks, etc. ......
    you just here Let’s talk about the first three implementation methods listed above.

Lazy man

    The biggest feature of the lazy style is that it is initialized only the first time (lazy loading, which avoids waste of memory resources to the extreme). It is simple to implement, but the disadvantage is that it does not realize multi-thread safety .

code show as below:

public class Singleton
{
    
    
    private static Singleton instance;
	
	//同样地,用私有化的构造函数来防止外界进行实例化
    Singleton(){
    
    }

    //提供给外界进行调用实例的方法,当然,也可以使用属性来进行代替
    public static Singleton GetSingleton() 
    {
    
    
        //如果进行调用时instance为null则进行初始化
        if (instance == null) 
        {
    
    
            instance = new Singleton();
        }
        return instance;
    }

}


Hungry Chinese

    Since there is a lazy man, it is natural to have a hungry man who is more diligent. As the name suggests, it is different from the lazy man which is initialized only at the first call.

When the instance is declared, it is initialized ,

code show as below:

public class Singleton
{
    
    
	//在进行实例声明的时候就完成初始化
    private static Singleton instance = new Singleton();
	
	//同样地,用私有化的构造函数限制外界进行实例化
    Singleton(){
    
    }

    //提供给外界进行调用实例的方法
    public static Singleton GetSingleton() 
    {
    
    
        return instance;
    }

}

    Looking at it this way, do you think there is little difference between the hungry style and the lazy style, but in fact there is a big difference between them, that is

The hungry man can achieve thread safety ,

Because it has already been initialized when it is declared, but therefore

It is easy to produce garbage objects in singletons that are not necessarily used, and waste memory


Static inner class

    The method of static inner class is slightly more complicated in implementation than the above two, but it also takes into account lazy loding and multi-thread safety.

code show as below:

public class Singleton
{
    
    
    Singleton(){
    
    }

    //提供给外界进行调用实例的方法
    public static Singleton GetSingleton() 
    {
    
    
        return InitSingleton.Instance;
    }

    //使用静态内部类完成初始化
    private static class InitSingleton 
    {
    
     
        public static Singleton Instance = new Singleton();
    }
}

    So the question is again, how do static inner classes achieve both?

    We know that the initialization of static members is performed when the class is loaded, and before we have called the GetSingleton() method, the InitSingleton class has not made any calls ,
    so naturally, the Singleton singleton has not been initialized .

The multi-thread safe implementation of the hungry man and the same type of;



Efficient application

    The realization of the singleton pattern is solved, but is it too troublesome to write this when each class needs to implement a singleton?

    So here, it’s the turn of encapsulation and inheritance in object-oriented thinking:
encapsulate the singleton pattern into a base class, and other classes that need to implement the singleton pattern only need to inherit the singleton pattern class.

The base class of singleton pattern is as follows (take hungry Chinese as an example):


public class Singleton<T> : MonoBehaviour where T : Component
{
    
    
    protected static GameObject SLT;
    protected static T instance;

    public static T Instance
    {
    
    
        get
        {
    
    
            if (instance == null)
            {
    
    
                if (SLT == null) 
                {
    
    
                	//负责进行调用的媒介
                    SLT = GameObject.Find("GlobalController").gameObject;
                }
                instance = SLT.GetComponent<T>();
            }
            return instance;
        }
    }

    protected Singleton(){
    
    }
}

When the subclass inherits, it only needs to be in the following form:
Subclass inheritance
but it cannot be called in this way . The script of the subclass must be mounted on the calling media object in order to access it . An empty object can be used to specifically mount it. And a singleton script that manages these global controls

Guess you like

Origin blog.csdn.net/Jourofant/article/details/108578615