栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

[设计模式、C++、go]创建型模式:单例模式

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[设计模式、C++、go]创建型模式:单例模式

文章目录
  • 单例模式
    • 介绍
    • 类图
    • 代码实现
      • C++
        • 懒汉模式:
        • 饿汉模式
        • 两种模式的比较
      • go
        • 饿汉模式
        • 懒汉模式
      • 场景
      • 优缺点
  • 扩展(产生固定数量的对象)

单例模式 介绍

单例模式(Singleton Pattern)是最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
其定义为:
Ensure a class has only one instance, and provide a global point of accessto it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
关键代码:构造函数是私有的。
判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

类图

代码实现

单例模式的代码实现,又分为了懒汉模式和饿汉模式;两者最主要的区别,在于单例对象的初始化时机,懒汉模式,是在需要只用的时候才会进行初始化;而饿汉模式,则一开始就会进行初始化

C++ 懒汉模式:
#include
#include
using namespace std;
//单例类
class Singleton{
private:
     Singleton(){}
 public:
//将获取单例对象的函数设置为static ,可以使用Singleton::GetInstance调用
  static Singleton* GetInstance(){
  //保证线程安全和效率,使用了双重检验+锁的形式
  //当有多个线程的场景时,我们要完成初始化一个对象的任务时,必须使用锁
  
  //上方的代码完全可以保证线程安全的需求,为什么还要加一层判断呢?
  //提高效率,当单例对象被初始化时,我们也需要判断一下,直接返回,不需要争夺互斥锁
      if(_instance==nullptr){
        _mutex.lock();        
        if(_instance==nullptr){
          _instance=new Singleton;
        }
        _mutex.unlock();
      }
      return _instance;
  }
 private:
   static Singleton* _instance;
   static mutex _mutex;
};
Singleton* Singleton::_instance =nullptr;
mutex Singleton::_mutex;

饿汉模式
#include
using namespace std;

class Singleton{
private:
     Singleton(){}
  public:
    static Singleton* GetInstance(){
          return _instance;
    }
  private:
   static Singleton* _instance;
};

Singleton* Singleton::_instance=new Singleton;
两种模式的比较
懒汉模式饿汉模式
线程安全线程不安全,需要加锁控制线程安全
优点第一次调用才初始化,避免内存浪费没有加锁,执行效率会提高
缺点必须加锁才能保证单例,但加锁会影响效率类加载时就初始化,浪费内存
go 饿汉模式
package Singleton
//结构体,名称首个字母小写,仅能在本文件使用
type singleton struct{
}
//接口,名称首字母大写,可以其他文件使用
type Singleton interface{
}

var (
//初始化一个全局变量
   _instance *singleton=&singleton{}
)

func GetSingletonInstance()Singleton{
     return _instance;
}

懒汉模式
package Singleton

import (
"sync"
"fmt"
)

type Singleton interface{
}
type singleton struct{
}

var (
     instance *singleton  
     once sync.Once        
)

func GetSingletonInstance() Singleton{
    once.Do(func(){
         instance=&singleton{}
         fmt.Println("create singleton")
    })
    return instance;
}

场景

1、要求生产唯一序列号。
2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

优缺点

优点:
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。
缺点:
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

扩展(产生固定数量的对象)
#include
#include
#include
using namespace std;


class Singleton{
   private:
      Singleton(){
      }
   public:
      static Singleton* GetInstance(){
           if(_instance.empty()){
               _mutex.lock();
               if(_instance.empty()){
                  for(int i=0;i<_instanceCount;i++){
                       Singleton* tmp=new Singleton;
                       _instance.push_back(tmp);
                  } 
               }
               _mutex.unlock();
           }
           //随机返回对象
           int number=rand()%_instanceCount;
           return _instance[number];
      }   
   private:
      //存放对象的容器
      static vector _instance;
      //产生对象的个数
      static int _instanceCount;
      static mutex _mutex;
};
int Singleton::_instanceCount=2;
vector Singleton::_instance;
mutex Singleton::_mutex;

int main(){
   for(int i=0;i<10;i++){
        printf("%xn",Singleton::GetInstance());  
   }
   return 0;
}

参考:菜鸟教程

如果本篇博客有任何错误和建议,欢迎伙伴们留言哦
此外,

可以点个赞,留下你的足迹哦!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/906384.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号