动机(Motivation):
    在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率

意图:
    保证一个类仅有一个实例,并提供一个访问它的全局访问点。

适用性:
   (1)当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
   (2)当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

代码实现:
(1)单线程Singleton实现

/// <summary>
/// 单例类
/// </summary>
public class SingleThread_Singleton_Class { //静态属性,提供全局访问点
private static SingleThread_Singleton_Class instance=null;
public static SingleThread_Singleton_Class Instance
{
get{
if (instance==null) {
instance = new SingleThread_Singleton_Class ();
}
return instance;
}
}
//私有的构造函数保证该类不能在其他类里实例化,即不能在其他类里new
private SingleThread_Singleton_Class(){} //用于单例测试
public void Print()
{
UnityEngine.Debug.Log ("我是单例类");
}
}

以上代码在单线程情况下不会出现任何问题。但是在多线程的情况下却不是安全的。
如两个线程同时运行到 if (instance == null)判断是否被实例化,一个线程判断为True后,在进行创建
 instance = new SingleThread_Singleton();之前,另一个线程也判断(instance == null),结果也为True.
这样就就违背了Singleton模式的原则(保证一个类仅有一个实例)。
怎样在多线程情况下实现Singleton?

(2)多线程Singleton实现:

public class MultiThread_Singleton {

    private static volatile MultiThread_Singleton instance=null;
private static object locker=new object();
private MultiThread_Singleton (){}
public static MultiThread_Singleton Instance
{
get{
if (instance==null) {
lock (locker) {
if (instance==null) {
instance = new MultiThread_Singleton ();
}
}
}
return instance;
}
} private int i=;
public void Print()
{
i++;
UnityEngine.Debug.Log ("第 "+i+" 次打印");
}
}

此程序对多线程是安全的,使用了一个辅助对象locker,保证只有一个线程创建实例(如果instance为空,保证只有一个线程instance = new MultiThread_Singleton();创建唯一的一个实例)。(Double Check)
请注意一个关键字volatile,如果去掉这个关键字,还是有可能发生线程不是安全的。
volatile 保证严格意义的多线程编译器在代码编译时对指令不进行微调。

(3)静态Singleton实现

public class Static_Singleton {
public static readonly Static_Singleton Instance = new Static_Singleton ();
private Static_Singleton() {
} public void Print()
{
Debug.Log ("我是静态单例");
}
}

优点: 简洁,易懂
缺点: 不可以实现带参数实例的创建。

(4)Unity Singleton脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 单例脚本
/// </summary>
public class SingleThread_Singleton_Script : MonoBehaviour {
private SingleThread_Singleton_Script(){}
public static SingleThread_Singleton_Script instance;
void Awake()
{
instance = this;//初始化
} public void Print()
{
Debug.Log ("我是单例脚本");
}
}

风险:

1、外部类依然可以同过GetComponent<>的形式实例化出该对象。

2、当单例脚本一旦被初始化后,即当程序运行后,从场景中去掉单例脚本组件,还是可以会执行该类的相关方法

最新文章

  1. 微信JSSDK javascript 开发 代码片段,仅供参考
  2. 把textarea右下角的灰点去掉
  3. Java NIO教程 Channel
  4. c# datagridview按条件搜索查询过滤
  5. js格式化日期,获取当月的第一天,与最后一天.
  6. webbroswer 后台注入脚本 的方法
  7. HDU ACM 1081 To The Max-&amp;gt;最大子矩阵
  8. 如何在appconfig中配置服务的ip
  9. UVA 1426 - Discrete Square Roots(数论)
  10. Ext.define(override)
  11. WinForm界面设计优化过程
  12. 2017.12.10《“剑锋OI”普及组多校联盟系列赛(14)#Sooke#Kornal 的课余时间 》分析报告
  13. android之RefBase
  14. SprirngBoot微服务之间的交互—— restTemplate
  15. 教你如何使用云服务器去搭建SS
  16. SSH端口转发详解及实例-转载
  17. Github 指令上手 --- 分支
  18. VSTO:使用C#开发Excel、Word【5】
  19. php随手记
  20. SCCM2012 R2实战系列之九:OSD(中)--捕获镜像

热门文章

  1. 问题集锦 ~ jQuery
  2. Codeforces 987B. High School: Become Human
  3. 基于localStorage的登录注册
  4. hiho1469 - 简单dp
  5. 设置div内的内容不能被选中
  6. yii2.0 发送邮件带word小附件
  7. C语言传参的类型匹配
  8. 洛谷 P1026 统计单词个数 (分组+子串预处理)(分组型dp再次总结)
  9. 紫书 习题 8-1 UVa 1149(贪心)
  10. 启动bind时报none:0: open: /etc/named/named.conf: file not found