设计模式(4)-序列生成器之单例模式

场景:序列生成器

系统中统一的序列生成程序,整个系统统一一套!那么就用单例模式吧!

首先看看单例模式

1)类持有一个自己的实例,而且还是个静态实例。

2)类的构造函数为私有属性。

3)用以获得实例的方法为静态方法。

看看类图

 

然后看一段试例程序:

#include <iostream>
 
using namespace std;
 
class Singleton{
private:  
    Singleton();//注意:构造方法私有  
    virtual ~Singleton();  
    static Singleton* instance;//惟一实例  
    int var;//成员变量(用于测试)  
public:  
    static Singleton* GetInstance();//工厂方法(用来获得实例)  
    int getVar();//获得var的值  
    void setVar(int);//设置var的值
};
//构造方法实现
Singleton::Singleton()  
{  
    this->var = 20;  
    cout<<"Singleton Constructor"<<endl;  
}
Singleton::~Singleton()
{
    if(instance != NULL)
    {
        delete instance;
    }
}
//初始化静态成员  
//Singleton* Singleton::instance=new Singleton(); 
Singleton* Singleton::instance=NULL;
Singleton* Singleton::GetInstance()  
{  
    if(instance == NULL)
    {
        instance = new Singleton();
    }
    return instance;  
}  
//seter && getter含数  
int Singleton::getVar()  
{  
    return this->var;  
}  
void Singleton::setVar(int var)  
{  
    this->var = var;  
}  
 
int main(int argc, char* argv[])
{
    Singleton *ton1 = Singleton::GetInstance();
    Singleton *ton2 = Singleton::GetInstance();
    cout<<"ton1 var = "<<ton1->getVar()<<endl;  
    ton1->setVar(150); 
    cout<<"ton2 var = "<<ton2->getVar()<<endl;
    return 0;
}

1、构造方法私有

那么,就意味着,只能在Singleton的成员函数中,才能调用Singleton的构造函数来创建实例。在Singleton之外,不能创建Singleton对象的实例。

2、代码中,定义了GetInstance方法,只能通过GetInstance方法来获取Singleton对象的实例,单例就是在GetInstance方法中控制的。

首先,Singleton有一个
static Singleton* instance;//惟一实例 

Singleton* Singleton::instance=NULL;
在这里初始化为NULL。

Singleton* Singleton::GetInstance()  
{  
 if(instance == NULL)
 {
  instance = new Singleton();
 }
 return instance;  
}  

上面的函数,就是通过instance来实现单例的。

当第一次调用GetInstance时,instance 为NULL,所以会执行
instance = new Singleton();
把这个新建的实例保存到静态成员instance,并返回这个指针。

第二次到第N次调用GetInstance时,由于instance不为空,所以会直接返回instance 。也就是第一次调用GetInstance创建的那个实例。


所以这样就实现了,单实例。


意思就是说,Singleton对象的实例,只会被创建一次,就是说内存中,只存在一个Singleton的实例,就是所谓,单实例。

弄个生成单例的实例程序吧!

#include <sys/sem.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <iostream> 
 
using namespace std; 
 
 
#define MAXID   9999
static struct sembuf op_open={1,-1,0  };
 
class GenHH{
    private:
        GenHH();//注意:构造方法私有
        virtual ~GenHH();   
        static GenHH* instance;//惟一实例
        int opensem(key_t semkey);
        int creatsem(key_t semkey,int bigcount);
        int sem_open(int semid);
        unsigned int gen_seq();
    public:
        static GenHH* getInstance();//工厂方法(用来获得实例)
        unsigned int gen_hh();
}
 
GenHH::~GenHH()
{
    if(instance != NULL) 
    
        delete instance; 
    }
}
 
//初始化静态成员
GenHH* GenHH::instance=NULL;
GenHH* GenHH::getInstance()
{
    if(instance == NULL) 
    
        instance = new Singleton(); 
    
    return instance;
}
 
unsigned int GenHH::gen_hh()
{
    unsigned int hh;
    char    chh[9];
 
    memset(chh,0,9);
 
    sprintf(chh,"%05d%04d",time(NULL)%100000,gen_seq());
 
    hh = atoi(chh);
 
    return hh;
}
 
unsigned int GenHH::gen_seq()
{
    int seq,kid;
    int semid,semval;
 
    struct timeval  tv;
 
 
    union semun {
        int val;
        struct semid_ds *buf;
                unsigned short *array;
        } semctl_arg;
     
 
    kid=ftok("/etc/hosts",'m');
    if(kid<0){
        printf("system Error! Can't find  /etc/hosts!\n");
        gettimeofday(&tv, NULL);
        return tv.tv_usec % MAXID ;
    }
 
    semid=opensem(kid);
    if(semid<=0){
        semid=creatsem(kid,MAXID);
        if(semid<0){
            gettimeofday(&tv, NULL);
            return tv.tv_usec % MAXID ;
        }
    }
 
    semval=semctl(semid,1,GETVAL,0);
    if(semval<=2){
        semctl_arg.val=MAXID;
                if ((semctl(semid,1,SETVAL,semctl_arg)) < 0 ){
            gettimeofday(&tv, NULL);
            return tv.tv_usec % MAXID ;
        }
    }
     
    sem_open(semid);
    semval=semctl(semid,1,GETVAL,0);
 
 
    return MAXID-semval;
}
 
int GenHH::opensem(key_t semkey)
{
    int semid;
 
    semid=semget(semkey,2,0);
    if(semid<0){
            printf("semaphoreid get error!\n");
            return -1;
    }
 
     return semid;
}
 
int GenHH::creatsem(key_t semkey,int bigcount)
{
    int semid,semval;
    union semun {
        int val;
        struct semid_ds *buf;
                unsigned short *array;
    } semctl_arg;
 
    semid=semget(semkey,2,IPC_CREAT|0600);
    if(semid<0){
        return -1;
    }
 
    if((semval=semctl(semid,1,GETVAL,0))<0)
        printf("GETVAL error!\n");
    else if(semval==0){
        semctl_arg.val=1;
        if(semctl(semid,0,SETVAL,semctl_arg)<0)
            printf("SETVAL error\n");
 
        semctl_arg.val=bigcount;
        if(( semctl(semid,1,SETVAL,semctl_arg)) < 0 )
            printf("setval error\n");
    }
 
    return semid;
}
 
int GenHH::sem_open(int semid)
{
    while(( semop(semid,&op_open,1) ) < 0 ){
        if( errno==EINTR ) {
            usleep(5000);
            continue;
        }
        printf("sem op_open error!\n");
        return -1;
    }
    return 0;
}
 
int main(int argc, char* argv[]) 
{
    GenHH *genHH1 = GenHH::getInstance();
    GenHH *genHH2 = GenHH::getInstance();
 
    cout<<genHH1->gen_hh()<<endl;
    cout<<genHH2->gen_hh()<<endl;
    return 0;
}
posted @   skyme  阅读(658)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示