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

简介:

场景:序列生成器

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

首先看看单例模式

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

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

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

看看类图

2011041320233414.jpg

然后看一段试例程序:


#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;
}


目录
相关文章
|
24天前
|
设计模式 安全 测试技术
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
58 0
|
1月前
|
设计模式 缓存 安全
【设计模式】单例模式:确保类只有一个实例
【设计模式】单例模式:确保类只有一个实例
20 0
|
3月前
|
设计模式 安全 Java
设计模式-单例模式
设计模式-单例模式
36 0
|
30天前
|
设计模式 安全 Java
设计模式之单例模式
设计模式之单例模式
|
4天前
|
设计模式 存储 Java
Java设计模式:解释一下单例模式(Singleton Pattern)。
`Singleton Pattern`是Java中的创建型设计模式,确保类只有一个实例并提供全局访问点。它通过私有化构造函数,用静态方法返回唯一的实例。类内静态变量存储此实例,对外仅通过静态方法访问。
12 1
|
30天前
|
设计模式 存储 缓存
设计模式之单例模式(C++)
设计模式之单例模式(C++)
21 2
|
1月前
|
设计模式 安全 Java
Java设计模式之单例模式
在软件工程中,单例模式是一种常用的设计模式,其核心目标是确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。Java作为一门广泛使用的编程语言,实现单例模式是面试和实际开发中的常见需求。
66 9
Java设计模式之单例模式
|
2月前
|
设计模式 存储 安全
【设计模式】创建型模式之单例模式(Golang实现)
【2月更文挑战第3天】一个类只允许创建一个对象或实例,而且自行实例化并向整个系统提供该实例,这个类就是一个单例类,它提供全局访问的方法。这种设计模式叫单例设计模式,简称单例模式。
34 1
|
3月前
|
设计模式 安全 Java
【设计模式】单例模式
【1月更文挑战第27天】【设计模式】单例模式
|
3月前
|
设计模式 安全 Java
Java设计模式—单例模式的实现方式和使用场景
那么为什么要有单例模式呢?这是因为有的对象的创建和销毁开销比较大,比如数据库的连接对象。所以我们就可以使用单例模式来对这些对象进行复用,从而避免频繁创建对象而造成大量的资源开销。
54 1