定义:
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
翻译:
有一个类,在程序进程中只有一个,程序开始时自动初始化自己的实例,程序结束后被释放,程序员不用也无法手动new或delete那样一个类的对象,这个类的唯一的对象会在整个进程中发挥作用,可随时被进程中的任何函数访问。
类图摘自设计模式之禅
特点:
单例类只有一个实例化的对象,这个对象的获取往往通过在类中设置Instance()/GetInstance()等方法获取,这是一般单例模式的默认命名,而只要在某个类中看到了instance()函数,就可以认为这个类是单例类,其数据从头到尾只有一份,在多线程访问中也只有一份,所有关于其数据的 *** 作均有必要加锁。
单例模式的优点:
1.内存中只有一个实例,减少内存开支,当一个对象要频繁创建和销毁且无法优化创建和销毁过程时优势明显。
2.减少系统性能开销,若创建一个对象需要较多资源时,如读取配置,产生依赖对象等,则可通过应用启动时直接产生一个单例对象,然后永久驻留内存的方法解决。
3.避免对资源的多重占用,如写文件动作,由于只有一个实例在内存中,就避免了对同一资源的同时写 *** 作。
4.在系统设置了全局访问点,优化和共享资源访问,如设计一个单例类,负责所有数据表的映射处理。
单例模式的缺点:
1.一般无接口,扩展就得改代码。
2.对测试不友好,并行开发环境中,单例完不成,测试动不了。
3.与单一职责原则冲突,一个类应只实现一个逻辑,单不单视环境而定。
4.在需求很大的情况下,单例类的处理效率上有明显劣势。
使用场景:
1 要求生成唯一序列号的环境
2 整个项目中需要一个共享访问点或共享数据库,如计数器,可以不把每次刷新都记录到数据库中,用单例模式保持计数器的值,并确保线程安全。
3 创建一个对象需要消耗的资源过多,如访问IO和数据库等资源。
4 需要定义大量静态常量与静态方法(工具类)的环境可用单例模式,也可直接声明为static。
代码示例:草民拜见皇上
皇上类:
class King { public: static King* GetInstance(); string GetName(); private: King(); static King* mKing; string mstrName; }; King* King::mKing = new King(); King::King() { string tmpNmae = ""; mstrName = tmpNmae; } King* King::GetInstance() { if (mKing == nullptr) { mKing = new King(); } return mKing; } string King::GetName() { return mstrName; }
百姓类:
class citizen { public: void BowToKing(King* KingPtr); }; void citizen::BowToKing(King* KingPtr) { cout << "草民拜见皇上" << KingPtr->GetName() << endl; }
测试函数:
void func() { citizen* CaoMing01 = new citizen(); citizen* CaoMing02 = new citizen(); citizen* CaoMing03 = new citizen(); citizen* CaoMing04 = new citizen(); CaoMing01->BowToKing(King::GetInstance()); CaoMing02->BowToKing(King::GetInstance()); CaoMing03->BowToKing(King::GetInstance()); CaoMing04->BowToKing(King::GetInstance()); delete CaoMing01; delete CaoMing02; delete CaoMing03; delete CaoMing04; } int main() { func(); return 0; }
运行结果:
可以看到,百姓类citizen的示例都需要手动使用new实例化和使用delete释放,而皇帝类则不需要手动创建或释放,而且在函数中可以通过King::GetInstance()直接访问,不受对象生命周期的影响,在某些过程中需要共用数据或方法时,单例模式十分好用。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)