一、使用Sington单例模式的动机(Motivation)

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

大多数类用的是常规的构造器,所以往往能创建很多实例,那么如何绕过常规的构造器,并且提供一种机制(设计模式)来保证一个类只有一个实例。

二、使用Singtong(单例设计模式)的意图

保证一个类只有一个实例,并且提供一个该实例的全局访问点

三、结构

四、使用Singleton(单例设计模式)需要注意的几个点

1、Singleton模式中的实例构造器可以设置成protected,方便子类继承

2、Singleton模式一般不要支持ICloneable接口,因为这可能会创建出多个实例,这与Singleton模式的初中所违背

3、Singleton模式也不要支持序列化,这也可能创建出多个对象实例

4、Singleton只考虑了对象创建的管理,并没有考虑对象销毁的管理,就支持垃圾回收的平台和对象来讲,这么点开销,一般没有必要对其进行特殊的管理,除非这个类超级大(但是如果这个类如果很大的话,那这个类需要重构).

5、不能应对多线程的情况,如果在多线程环境下,下面的紧接着的实例代码可能会创建出多个实例。

五、代码演示

1、单线程Singleton(单例模式)实现         (最基本的一种)

using System;
namespace Singleton
{
class Program
{
static void Main(string[] args)
{
Singleton1 s1 = Singleton1.getInstance();
Singleton1 s2 = Singleton1.getInstance();
Console.WriteLine("s1和s2{0}同一个实例", (Object.ReferenceEquals(s1, s2) == true) == true ? "是" : "不是");//输出:s1和s2是同一个实例
}
}
/*
* (单线程)单例模式的第一种实现方式(最基本的实现方法)
* 目地:实现用单例模式实现的类只有一个实例,而且全局共享这个实例
*/
class Singleton1
{
private static Singleton1 instance { get; set; }
//这里使用私有构造函数的原因是:因为如果我们不给类定义构造函数,那么C#编译器会给当前类加一个默认的共有的构造器函数,但是如果我们在类中定义了构造函数那么C#编译器
//将不会在该类中添加默认的共有构造器函数,所以我们在这里定义一个私有构造器,那么C#编译器将不会给类添加共有的构造器,而且这个构造器将不会被外界调用
//所以该类无法被实例化,也就是new出来
private Singleton1() { } //1、既然Singleton1类无法在外部被实例化,那么我们就必须在内部Singleton1实例化,然后提供一个公有的方法将该实例返回 public static Singleton1 getInstance() { //这里的if判断是保证该实例全局唯一,保证外部调用的Singleton1的实例是唯一的
if (instance == null)
{
instance = new Singleton1();
}
return instance;
} }
}

分析:根据控制台的输出可以肯定的是,Singleton1.getInstance()创建出来的实例都是同一个实例,但是这里存在一个问题,这只是在单线程的情况下是这样的,如果在多线程的情况下,假设两个线程同时判断if(instance==null),那么接下来会new出两个不同的实例。所以上面的代码仅适用于单线程的情况!

2、多线程单例模式

using System;
namespace Singleton
{
class SingleByManyThread
{
static void Main(string[] args)
{ }
}
class Singleton
{
//volatile关键字的作用是让编译器严格按照下面代码的逻辑来执行
//如果不加volatile,那么C#编译器在莫种情况下可能会对下面的多线程处理代码做微调,那么也可能出现两个实例的情况 private static volatile Singleton instance { get; set; }
//给lock语句提供的Object对象,不能是值或者string类型,具体原因参考多线程lock语句的规范
private static Object lockHelper = new object();
//1、将构造器函数设置私有的原因是:外部对象调用本类时,无法通过new的方式,只能通过本类内部提供的方法来获取本类的实例
//2、这里注意:如果不给类定义构造器函数,那么C#编译器会给类添加一个默认的公有构造器函数,如果我们自己定义了,那么C#编译器就不会自己定义了
private Singleton() { } //将本类的实例通过本类公开的属性给外部类(对象)访问
public static Singleton Instance
{
//这里做双重检查来保证多个线程不会同时进入if语句
get
{
if (instance == null)
{
//在多线程环境中,给单个线程加锁,防止在一个线程在访问lock内代码时,另一个线程也在方法,起到线程隔离的作用
//这样就解决了多线程环境下可能创建出两个Singleton实例的情况
lock (lockHelper)
{
if (instance==null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
}

3、既能解决多线程环境,也能实现Singleton模式的实现方法(单线程和多线程下都能实现Singleton模式(单例模式))的实现方法

using System;
namespace Singletons
{
class SingletonBests
{
static void Main(string[] args)
{ }
}
class SingletonBest
{
//这是一种专业术语叫"内联初始化"的创建的实例的方式
//用这种方式创建的SingletonBest实例C#编译器会在New SingletonBest()之前调用SingleBest1类中static静态构造器给Instance实例赋值
//C#编译器会给静态构造器加锁,所以不需要使用lock来解决多线程创建多个实例的问题
//这种模式结合前面两种模式共同的功能,但是存在一个问题
//因为静态构造器是个C#运行时生成,给系统调用的,所以无法利用构造函数对其进行初始化
public static readonly SingletonBest Instance = new SingletonBest();
private SingletonBest() { }
} //上面的内联初始化的方式等同于下面的创建方式
class SingleBest1
{
//现在内存中开辟Instance实例的空间,在通过静态构造器给Instance赋值
public static readonly SingleBest1 Instance;
//静态构造函数无法参数化
static SingleBest1()
{
Instance = new SingleBest1();
}
private SingleBest1() { }
}
}

4、解决"内联初试化"实现单例模式静态构造函数无法参数化的问题

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Singleton
{
class SingletonParametric
{
//当我们编写一个类时,大多数情况下,数据初始化的任务都会交给构造器函数
//但是这里我们使用的是内联初始化的方式来实现的单例模式,这种方式,创建实例会交给静态构造函数来实现
//而静态构造函数不能给他传递参数,应为静态构造函数是给系统调用的
//所以如果要使用内联初始化的方式来实现单例模式的情况下,初始化参数只能交给公开的方法和属性来实现
public static readonly SingletonParametric Instance = new SingletonParametric();
private SingletonParametric() { } //通过公开一个OnInit()来实现当前类的参数化
public void OnInit() { }
//通过公开属性的方式给当前实例传参
private int _x;
private int _y;
public int X
{
get { return _x; }
set { _x = value; }
}
public int Y
{
get { return _y; }
set { _y = value; }
} }
}

Sington单例模式(创建型模式)的更多相关文章

  1. 单例模式——创建型模式01

    1. 名称     单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类.单例模式是一种对象创建型模式. 2. 问题    ...

  2. [C#]设计模式-单例模式-创建型模式

    单例模式用于在整个软件系统当中保持唯一实例,在 C# 当中最能够体现此概念的就是静态类,静态类的生命周期是跟随整个程序,并且在整个程序中仅保有一个实例. 不过在这里我们不再详细阐述单例模式与静态类有什 ...

  3. 设计模式学习之单例模式(Singleton,创建型模式)(4)

    假如程序中有一个Person类,我的需求就是需要在整个应用程序中只能new一个Person,而且这个Person实例在应用程序中进行共享,那么我们该如何实现呢? 第一步: 新建一个Person类,类中 ...

  4. [19/04/22-星期一] GOF23_创建型模式(单例模式)

    一.概念 <Design Patterns: Elements of Reusable Object-Oriented Software>(即后述<设计模式>一书),由 Eri ...

  5. 设计模式01: Singleton 单例模式(创建型模式)

    Singleton 单例模式(创建型模式) 动机(Motivation)当进行软件开发是会有这样一种需求:在系统中只有存在一个实例才能确保它们的逻辑正确性.以及良好的效率.这应该是类设计者的责任,而不 ...

  6. java架构之路-(设计模式)五种创建型模式之单例模式

    设计模式自身一直不是很了解,但其实我们时刻都在使用这些设计模式的,java有23种设计模式和6大原则. 设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可 ...

  7. Java设计模式 - 单例模式(创建型模式)

    单例模式我在上学期看一些资料时候学习过,没想到这学期的软件体系结构就有设计模式学习,不过看似篇幅不大,介绍得比较简单,在这里我总结下单例模式,一来整理之前的笔记,二来也算是预习复习课程了. 概述 单例 ...

  8. Java设计模式——单例模式(创建型模式)

    概述   单例模式保证对于每一个类加载器,一个类仅有一个实例并且提供全局的访问.其是一种对象创建型模式.对于单例模式主要适用以下几个场景: 系统只需要一个实例对象,如提供一个唯一的序列号生成器 客户调 ...

  9. Java设计模式之创建型模式

    创建型模式分为五类:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 一.工厂方法模式:接口-实现类.工厂类

随机推荐

  1. Java中读取.properties配置文件的通用类

    由于Java中读取配置文件的代码比较固定,所以可以将读取配置文件的那部分功能单独作为一个类,以后可以复用.为了能够达到复用的目的,不能由配置文件中每一个属性生成一个函数去读取,我们需要一种通用的方法读 ...

  2. HDU 1009 FatMouse' Trade (贪心算法)

    题意:就是老鼠要用猫粮换粮食,第i个房间一些东西,要用东西去换,可以不全换.问给定的猫粮最多能换多少粮食. 析:贪心算法.我们先算出来每个房间物品的平均价格是多少,肯定越低越好,并且如果能全换就全换, ...

  3. javascript实现责任链设计模式

    javascript实现责任链设计模式 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿这条链传递该请求,直到有一个对象处理他为止. 这是Gof的定义 ...

  4. 3D UI场景中,把XY平面的尺寸映射为屏幕像素的数学模型推导

    概述及目录(版权所有,请勿转载,欢迎读者提出错误) 之前用kanzi的3D UI引擎和cocos-2d的时候都有遇到过这个问题,就如何把3D场景中的XY平面的尺寸映射为与屏幕像素一一对应的,即XY平面 ...

  5. Codeforces805 A. Fake NP 2017-05-05 08:30 327人阅读 评论(0) 收藏

    A. Fake NP time limit per test 1 second memory limit per test 256 megabytes input standard input out ...

  6. codevs 1012

    题目描述 Description 给出n和n个整数,希望你从小到大给他们排序 输入描述 Input Description 第一行一个正整数n 第二行n个用空格隔开的整数 输出描述 Output De ...

  7. 集合(四)HashMap

    之前的List,讲了ArrayList.LinkedList,最后讲到了CopyOnWriteArrayList,就前两者而言,反映的是两种思想: (1)ArrayList以数组形式实现,顺序插入.查 ...

  8. SQLite 编译错误 - 试图加载格式不正确的程序

    刚开始用SQLite,刚开始写了一个小程序,连接数据库的时候出现了问题,提示试图加载格式不正确的程序, 原因是我当前工程的目标平台是X86,改成Any CPU之后问题就解决了.如下图:

  9. 使用datepicker日期插件

    使用datepicker日期插件 在引入<jquery.js> <bootstrap.js><datepicker.js>之后 引用<bootstrap.cs ...

  10. CSS2.1SPEC:视觉格式化模型之包含块

    原汁原味的才是最有味道的,在阅读CSS标准时对这一点的体会更加深刻了,阅读文档后的一大感觉就是很多看上去理所应当的样式表现也都有了对应的支持机制.本文首先从包含块写起,一方面总结标准中相应的阐述,并且 ...