设计模式(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;
}


目录
相关文章
|
4天前
|
设计模式 存储 前端开发
前端必须掌握的设计模式——单例模式
单例模式是一种简单的创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。适用于窗口对象、登录弹窗等场景,优点包括易于维护、访问和低消耗,但也有安全隐患、可能形成巨石对象及扩展性差等缺点。文中展示了JavaScript和TypeScript的实现方法。
|
9天前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
15 2
|
23天前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
30 4
|
1月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
15天前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
1月前
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入理解与应用
【10月更文挑战第22天】 在软件开发中,设计模式是解决特定问题的通用解决方案。本文将通过通俗易懂的语言和实例,深入探讨PHP中单例模式的概念、实现方法及其在实际开发中的应用,帮助读者更好地理解和运用这一重要的设计模式。
19 1
|
23天前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
23 0
|
2月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
27 0
|
2月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
本教程详细讲解了Kotlin中的单例模式实现,包括饿汉式、懒汉式、双重检查锁、静态内部类及枚举类等方法,适合需要深入了解Kotlin单例模式的开发者。快速学习者可参考“简洁”系列教程。
36 0
|
2月前
|
设计模式 存储 数据库连接
Python编程中的设计模式之美:单例模式的妙用与实现###
本文将深入浅出地探讨Python编程中的一种重要设计模式——单例模式。通过生动的比喻、清晰的逻辑和实用的代码示例,让读者轻松理解单例模式的核心概念、应用场景及如何在Python中高效实现。无论是初学者还是有经验的开发者,都能从中获得启发,提升对设计模式的理解和应用能力。 ###