Unity 设计模式 之 单例模式(普通型(new)泛型单例 \ 继承 MonoBehaviour 的泛型单例)
目录
Unity 设计模式 之 单例模式(普通型(new)泛型单例 \ 继承 MonoBehaviour 的泛型单例)
一、简单介绍
Unity编程众所周知,它是属于脚本化,脚本没有一个具体的概念跟架构,导致在项目过程中,经常出现哪里需要实现什么功能,就随便添加脚本,结果,就造成了一片混乱,不好管理。更有甚者,自己的写的代码闲置一段时间后,再去想找某个功能的实现,都要在视图中翻来覆去找半天。所以开发游戏中需要尽量遵循一些原则,予以规范化
开闭原则 | 面对需求,对程序的改动是通过增加新代码进行的,而不是改变原来的标题 |
依赖倒转原则 | 高层模块不应该依赖底层模块,两个都应该依赖与抽象;抽象不应该依赖于细节,细节应该依赖于抽象。所以要针对接口编程,不要针对实现编程。 |
里氏代换原则 | 由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象 |
单一职责原则 | 一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类,就一个类而言,应该仅有一个引起它变化的原因 |
接口隔离原则 | 接口隔离原则是指使用多个专门的接口,而不使用单一的总接口。每一个接口应该承担一种相对独立的角色,不多不少,不干不该干的事,该干的事都要干 |
合成复用原则 | 合成复用原则就是指在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分;新对象通过委派调用已有对象的方法达到复用其已有功能的目的。简言之:要尽量使用组合/聚合关系,少用继承 |
迪米特法则 | 一个软件实体应当尽可能少的与其他实体发生相互作用。在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限 |
编程中,遵循以上原则,使代码
- 提高代码复用率
- 适应变化
- 可维护性
- 可扩展性
二、单例模式(Singleton Pattern)
是最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
三、注意事项
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
四、普通型(new)泛型单例模式
方法一:
public abstract class Singleton<T> where T : class, new()
{
private static T instance = null;
// 多线程安全机制
private static readonly object locker = new object();
public static T Instance
{
get
{
lock (locker)
{
if (instance == null)
instance = new T();
return instance;
}
}
}
}
方法二:
using System;
using System.Reflection;
/// <summary>
/// 单例
/// 继承需要一个非公有的无参构造函数
/// </summary>
/// <typeparam name="T">类名的泛型</typeparam>
public abstract class Singleton<T> where T : class
{
private static T instance = null;
// 多线程安全机制
private static readonly object locker = new object();
public static T Instance
{
get
{
// 线程锁
lock (locker)
{
if (null == instance)
{
// 反射获取实例
var octors = typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic) ;
// 获取无参数的非公共构造函数
var octor = Array.Find(octors, c => c.GetParameters().Length == 0);
// 没有则提示没有私有的构造函数
if (null == octor)
{
throw new Exception("No NonPublic constructor without 0 parameter");
}
// 实例化
instance = octor.Invoke(null) as T;
}
return instance;
}
}
}
/// <summary>
/// 构造函数
/// 避免外界new
/// </summary>
protected Singleton() { }
}
五、继承 MonoBehaviour 的泛型单例模式
using UnityEngine;
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance = null;
private static readonly object locker = new object();
private static bool bAppQuitting;
public static T Instance
{
get
{
if (bAppQuitting)
{
instance = null;
return instance;
}
lock (locker)
{
if (instance == null)
{
// 保证场景中只有一个 单例
T[] managers = Object.FindObjectsOfType(typeof(T)) as T[];
if (managers.Length != 0)
{
if (managers.Length == 1)
{
instance = managers[0];
instance.gameObject.name = typeof(T).Name;
return instance;
}
else
{
Debug.LogError("Class " + typeof(T).Name + " exists multiple times in violation of singleton pattern. Destroying all copies");
foreach (T manager in managers)
{
Destroy(manager.gameObject);
}
}
}
var singleton = new GameObject();
instance = singleton.AddComponent<T>();
singleton.name = "(singleton)" + typeof(T);
singleton.hideFlags = HideFlags.None;
DontDestroyOnLoad(singleton);
}
instance.hideFlags = HideFlags.None;
return instance;
}
}
}
protected virtual void Awake()
{
bAppQuitting = false;
}
protected virtual void OnDestroy()
{
bAppQuitting = true;
}
}
六、使用方式
1、继承泛型单例模式即可
public class Test1 : MonoSingleton<Test1>{}
// 方法一
public class Test2 : Singleton<Test2>{}
// 方法二
public class Test2 : Singleton<Test2>{{private Test2(){}}