动机(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、当单例脚本一旦被初始化后,即当程序运行后,从场景中去掉单例脚本组件,还是可以会执行该类的相关方法

Unity C# 设计模式(一)单例模式的更多相关文章

  1. Unity3d设计模式之单例模式

    单例模式我相信是所有设计模式之中运用最广泛的设计模式之一. 今天我们就来看看在unity中如何使用单例模式,在unity中,我们分两种单例,一种是继承monobehavior的单例,一种是普通单例. ...

  2. 设计模式之单例模式(Singleton)

    设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...

  3. GJM : C#设计模式(1)——单例模式

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

  4. java设计模式之单例模式(几种写法及比较)

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  5. 每天一个设计模式-4 单例模式(Singleton)

    每天一个设计模式-4 单例模式(Singleton) 1.实际生活的例子 有一天,你的自行车的某个螺丝钉松了,修车铺离你家比较远,而附近的五金店有卖扳手:因此,你决定去五金店买一个扳手,自己把螺丝钉固 ...

  6. 设计模式之单例模式的简单demo

    /* * 设计模式之单例模式的简单demo */ class Single { /* * 创建一个本类对象. * 和get/set方法思想一样,类不能直接调用对象 * 所以用private限制权限 * ...

  7. 设计模式之单例模式——Singleton

                        设计模式之单例模式--Singleton 设计意图: 保证类仅有一个实例,并且可以供应用程序全局使用.为了保证这一点,就需要这个类自己创建自己的对象,并且对外有 ...

  8. 10月27日PHP加载类、设计模式(单例模式和工厂模式)、面向对象的六大原则

    加载类可以使用include.require.require_once三种中的任意一种,每个关键字都有两种方法,但是这种方法的缺点是需要加载多少个php文件,就要写多少个加载类的方法.一般也就需要加载 ...

  9. java 23 - 2 设计模式之单例模式

    单例模式:保证类在内存中只有一个对象. 如何保证类在内存中只有一个对象呢?  A:把构造方法私有  B:在成员位置自己创建一个对象  C:通过一个公共的方法提供访问 单例模式之饿汉式: (一进来就造对 ...

  10. [转]JAVA设计模式之单例模式

    原文地址:http://blog.csdn.net/jason0539/article/details/23297037 概念: java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主 ...

随机推荐

  1. Android 自定义View 之利用ViewPager 实现画廊效果(滑动放大缩小)

    http://www.2cto.com/kf/201608/542107.html

  2. sql 分割日期

    datename(Year,CreateTime)   ==2017 datename(Month,CreateTime)   7 1.获取星期(显示中文如:星期一) Select DateName( ...

  3. 解码URLDecode和编码URLEnCode

    在前台往后台传递参数的时候,在前台进行编码,在后台接收参数的时候,用Decode进行解码: 如果url中包含特殊字符如:&.html标签 <tr><td>等导致url无 ...

  4. KVO VS isa : KVO 建立在 KVC 之上

    Key-Value Observing (KVO) 建立在 KVC 之上,它通过重写 KVC 和监听 setter 方法,向外发送通知. https://blog.csdn.net/y55091811 ...

  5. 在yii2.0中封装一个生成验证码的控制器

    frontend目录下/封装的验证码类: <?php namespace frontend\controllers; use yii\base\Controller; class CapathC ...

  6. 解决com.mysql.jdbc.PacketTooBigException: Packet for query is too large问题

    2017年05月10日 09:45:55 阅读数:1659 在做查询数据库操作时,报了以上错误,原因是MySQL的max_allowed_packet设置过小引起的,我一开始设置的是1M,后来改为了2 ...

  7. sql 技巧

    1.想把一张表的 某个字段或多个字段 的 所有数据 复制到另外一张表里  insert into 表名(字段) select (字段) from 表名 2.from Users u , IN(u.ro ...

  8. jsp页面跳转的路径问题

    <form class="box login" action="/graduation_system/BServlet" method="pos ...

  9. 洛谷 P4147 玉蟾宫 (最大子矩形问题)

    这道题用到了悬线法,非常牛逼,可以看这个论文. https://blog.csdn.net/twtsa/article/details/8120269 #include<cstdio> # ...

  10. 紫书 习题 11-4 UVa 1660 (网络流拆点法)

    这道题改了两天-- 因为这道题和节点有关, 所以就用拆点法解决节点的容量问题. 节点拆成两个点, 连一条弧容量为1, 表示只能经过一次. 然后图中的弧容量无限. 然后求最小割, 即最大流, 即为答案. ...