创建型设计模式之单例模式
一、含义
在一个进程或者线程里,对于一个类只有一个实例化对象,即内存中只有一个实例化对象
二、代码说明
由于是单例模式,只有一个对象,所以该类内部都是静态常量和静态方法,
具体来说,因为只有一个对象不能创建多个对象,创建对象就没什么意义了(直接用类表示对象即一个类就是一个对象),所以类内部都是静态的,不需创建就可使用(而且由于是静态的也确保每次调用都是属于类的内存空间,即只占一份内存空间也就是一个对象的内存空间)
在用C实现过程中也是参考这种思想,直接构造一个类的对象,而且不提供new这个类的对象的接口,具体实现如下:
单例模式使用场景:
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : SingletonPattenUsage.c 5 * Description : 单例模式的使用 6 7 book@book-desktop:/work/projects/test/DesignPatterns$ gcc -o SingletonPatternUsage SingletonPattern.c SingletonPatternUsage.c 8 book@book-desktop:/work/projects/test/DesignPatterns$ ./SingletonPatternUsage 9 This is:Singleton 10 SingletonGetId:12 11 12 * Created : 2017.07.02. 13 * Author : Yu Weifeng 14 * Function List : 15 * Last Modified : 16 * History : 17 ******************************************************************************/ 18 #include"stdio.h" 19 #include"malloc.h" 20 #include"stdlib.h" 21 #include"string.h" 22 #include"SingletonPattern.h" 23 24 25 26 27 /***************************************************************************** 28 -Fuction : main 29 -Description : 30 -Input : 31 -Output : 32 -Return : 33 * Modify Date Version Author Modification 34 * ----------------------------------------------- 35 * 2017/06/29 V1.0.0 Yu Weifeng Created 36 ******************************************************************************/ 37 int main(int argc,char **argv) 38 { 39 g_tSingleton.PrintInfo(); 40 g_tSingleton.SetId(12); 41 printf("SingletonGetId:%d ",g_tSingleton.GetId()); 42 43 return 0; 44 }
被调用者:
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : SingletonPattern.c 5 * Description : 单例模式 6 * Created : 2017.07.02. 7 * Author : Yu Weifeng 8 * Function List : 9 * Last Modified : 10 * History : 11 ******************************************************************************/ 12 #include"stdio.h" 13 #include"malloc.h" 14 #include"stdlib.h" 15 #include"string.h" 16 #include"SingletonPattern.h" 17 18 static void PrintInfo(); 19 static void SetId(int i_iId); 20 static int GetId(); 21 22 23 static char *g_strSingleton="Singleton";//私有变量 24 static int g_iId=0;//私有变量 25 26 27 28 //懒汉模式用到的时候才初始化,线程不安全(要加锁解决) 29 //一般使用饿汉模式,非常饿,迫不及待也就是一开始就做了(初始化了) 30 const T_Singleton g_tSingleton={ 31 .PrintInfo =PrintInfo, 32 .SetId =SetId, 33 .GetId =GetId, 34 }; 35 36 37 /***************************************************************************** 38 -Fuction : PrintInfo 39 -Description : 公有函数(单例模式所以才加了static) 40 -Input : 41 -Output : 42 -Return : 43 * Modify Date Version Author Modification 44 * ----------------------------------------------- 45 * 2017/06/29 V1.0.0 Yu Weifeng Created 46 ******************************************************************************/ 47 static void PrintInfo() 48 { 49 printf("This is:%s ",g_strSingleton); 50 } 51 52 /***************************************************************************** 53 -Fuction : SetId 54 -Description : 公有函数(单例模式所以才加了static) 55 -Input : 56 -Output : 57 -Return : 58 * Modify Date Version Author Modification 59 * ----------------------------------------------- 60 * 2017/06/29 V1.0.0 Yu Weifeng Created 61 ******************************************************************************/ 62 static void SetId(int i_iId) 63 { 64 g_iId=i_iId; 65 } 66 67 /***************************************************************************** 68 -Fuction : GetId 69 -Description : 公有函数(单例模式所以才加了static) 70 -Input : 71 -Output : 72 -Return : 73 * Modify Date Version Author Modification 74 * ----------------------------------------------- 75 * 2017/06/29 V1.0.0 Yu Weifeng Created 76 ******************************************************************************/ 77 static int GetId() 78 { 79 return g_iId; 80 }
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : SingletonPattern.h 5 * Description : 单例模式 6 * Created : 2017.07.02. 7 * Author : Yu Weifeng 8 * Function List : 9 * Last Modified : 10 * History : 11 ******************************************************************************/ 12 #ifndef SINGLETON_PATTERN_H 13 #define SINGLETON_PATTERN_H 14 15 16 typedef struct Singleton 17 { 18 void (*PrintInfo)(); 19 void (*SetId)(int i_iId); 20 int (*GetId)(); 21 }T_Singleton; 22 23 24 extern const T_Singleton g_tSingleton; 25 26 27 28 #endif
详细代码:
https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/CreationalDesignPatterns/SingletonPattern
执行结果:
book@book-desktop:/work/projects/test/DesignPatterns$ gcc -o SingletonPatternUsage SingletonPattern.c SingletonPatternUsage.c
book@book-desktop:/work/projects/test/DesignPatterns$ ./SingletonPatternUsage
This is:Singleton
SingletonGetId:12
三、使用场景
1.整个项目中需要一个共享访问点或共享数据
2.需要定义大量静态常量和静态方法的环境(当然也可以直接声明为static的方式)
3.创建一个对象需要消耗的资源过多
4.要求生成唯一序列号的环境
5.只需要一个对象的情况,同时类的对象只被一个线程使用时可以使用单例模式,显然,类的对象被多个线程使用时如果还使用单例模式就要考虑线程安全的问题(加锁操作等,操作就复杂了)
6.需要的对象是固定数目且不止一个的情况,可以使用有上限的多例模式(单例模式的扩展),至于线程安全问题,可以通过有几个线程就构造几个对象来解决。
多例模式:以同样的类构造固定数目的对象,外部创建对象只能使用固定的那些对象(已经构造好的那些对象)
7.在C语言中,如果私有变量一定要放在.c文件中(即放在内部),那么就要考虑使用单例模式或多例模式
四、优点
1.减少内存开支,减少了系统的性能开销
2.避免对资源的多重占用
3.可以在系统设置全局的访问点,优化和共享资源访问
五、缺点
1.与单一职责原则冲突,一个类应该只实现一个逻辑,而不关心它是否是单例的,单例模式把"要单例"和业务逻辑融合在一个类中
2.一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径
创建型设计模式包括,单例模式,工厂模式,抽象工厂模式,建造者模式,原型模式,由于封装性,C的对象都是函数的对象,并且创建多个对象比较耗内存,出于紧急性和重要性考虑,因此除了单例模式,其余模式放在行为型设计模式和结构型设计模式后再讨论