UFL1——单例模式基类

前置知识点

大体知识体系

  • C#相关知识点(C#四部曲)

细节知识点

  1. 面向对象(C#四部曲C#核心中)
  2. 静态、单例模式相关知识(C#四部曲之C#核心中)
  3. 泛型、泛型约束相关知识点(C#四部曲之C#进阶中)

单例模式

一般的单例模式差不多都会写类似于下面的这种形式,区别几乎只在于类名,该模式的特点是

  • 单例模式的类只能有一个实例化对象,由该类的静态私有变量instance​装载,外部不能实例化单例模式的类
  • 单例模式类只会在程序启动时,或者第一次调用静态Instance​属性时才会自己实例化一个对象,
    而静态Instance​属性是外部唯一能够调用单例模式唯一类对象的接口
  • 而由于单例模式类的构造函数是私有的,外部无法实例化一个对象,它保证了单例模式类对象是唯一的

单例模式的类可以在外部随时调用该类的Instance属性来调用该类的唯一对象

1
2
3
4
5
6
public class GameManager
{
private static GameManager instance = new GameManager(); //为该类写一个私有静态变量,并调用私有构造函数,装载该类的唯一的实例化对象
public static GameManager Instance => instance; //为该类写一个静态属性,使唯一装载该类的实例化对象的变量在外部只读,以可以调用该类的各种成员
private GameManager() { } //私有的无参构造函数,确保只有该类的私有静态变量可以构造该类的实例化对象,而外部不能,在外部第一次调用静态属性时会执行
}

为什么要写单例模式基类

用面向对象的思想避免代码冗余(多余、重复)
让使用单例模式的类直接继承该基类来复用静态私有变量的声明以及单例调用接口代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class TestMgr
{
//装载该单例类唯一实例的静态私有变量
private static TestMgr instance;

//通过属性调用单例对象,与方法获取的方式任选其一
public static TestMgr Instance
{
get
{
//当单例不存在时,先实例化
if (instance == null)
instance = new TestMgr();
return instance;
}
}

//通过方法调用单例对象,与属性获取的方式任选其一
public static TestMgr GetInstance()
{
if (instance == null)
instance = new TestMgr();
return instance;
}

//私有构造函数,用于顶掉无参构造函数,防止外部去实例化这个单例类
private TestMgr() { }
}

单例模式与静态类的区别

静态类也是只能用类名调用且不能实例化的类,它和单例模式类有什么区别呢?

  • 静态类的方法适合纯数据处理,因为不依赖其它对象实例,写入参数就可以,但这也是它的限制,方法里是不可调用它的实例对象的
  • 单例模式类,实际在第一次调用时它会在内部创建了实例化对象,之后都是在调用这个唯一的实例
  • 静态类不能过多,静态类将会一开始就需要将方法逻辑编译成本机代码(win,mac,linux)
    这就会在程序启动时形成过多cpu计算,而实例是在实例方法第一次被调用时才编译成本机代码(只编译一次)。
  • 所以应该尽量使用实例,有更好的内存管理gc释放,也会分散编译方法体的本机代码

单例模式基类实现

  • 不继承MonoBehaviour的单例模式基类
  • 继承MonoBehaviour的单例模式基类
  • 安全性问题解决
  • “饿汉”与“懒汉”单例模式