单实例模式

https://blog.csdn.net/lzm18064126848/article/details/50074887

 

https://blog.csdn.net/ab198604/article/details/19196315

 

需求大部分时候,我们把类的构造器定义成public访问权限,允许任何类自由创建这个类的实例对象,但是某些时候,允许其他类自由创建这个类的对象没有任何意义,还可能造成了系统性能的下降(因为创建一个对象的系统开销问题),例如系统可能自己hi有一个窗口管理器,一个假脱机打印设备或者一个数据库引擎访问点,这个时候如果在系统中创建多个对象就没有太大的时机意义,



如果一个类始终只能创建一个实例,则这个类就被称为单例类
这个时候我们就应该把类的构造器用private修饰,从而把这个类的所有构造器隐藏起来


根据封装型的原则:一旦把类的构造器隐藏起来,就需要提供一个public方法作为这个类的访问点,用于创建这个类的对象,且这个方法必须是static修饰(因为调用这个方法之前还不存在对象,因此调用这个方法不可能是对象,只能是类);

不仅如此,这个类还必须缓存已经创建的对象,不然这个类无法知道是不是已经创建了一个对象,也就无法只保证只创建了一个对象了,为此我们需要提供一个属性来保存曾经创建的对象,因为这个属性要被上面的静态方法访问,所以必须要用static修饰

其实这里隐含的知识为java初始化顺序



下面我们用程序来说明这一点[code=java]package cn.itcast.heima
class Singleton
{
//使用一个变量来缓存曾经创建的实例
private static Singleton instance;
//将构造器使用private修饰,隐藏该构造器
private Singleton(){}
//提供一个静态方法,用于返回Singleton实例
//该方法可以加入自定义的控制,保证只产生一个Singleton对象
public static Singleton getInstance()
{
//如果instance为null,表明还不曾创建Singleton对象
//如果instance不为null,则表明已经创建了Singleton对象,将不会执行该方法
if (instance == null)
{
//创建一个Singleton对象,并将其缓存起来
instance = new Singleton();
}
return instance;
}
}
public class TestSingleton
{
public static void main(String[] args)
{
//创建Singleton对象不能通过构造器,只能通过getInstance方法
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
//将输出true
System.out.println(s1 == s2);
}
}

 

 

 

 

 

单例模式是应用最多的一种设计模式,它要求每个类有且只能有一个实例对象,所以用C++设计一个单例模式的方法如下:

        1 构造函数声明为私有;   这样就保证了不能随意构造一个对象

        2 将拷贝构造函数与等号运算符声明为私有,并不提供他们的实现; 即禁止对象被拷贝。

        3 在类中声明一个静态的全局访问接口;

        4 声明一个静态的私有实例化指针;

        

class Singleton
{
public:
//全局访问接口
static Singleton *GetInstance()
{
if( instance_ == NULL )
{
instance_ = new Singleton;
}
return instance_;
}

~Singleton()
{
cout << "~Singleton"<< endl;
}

private:
Singleton(const Singleton& other);
Singleton & operator=(const Singleton & other);
Singleton()
{
cout << "Singleton"<<endl;
}


static Singleton *instance_; //引用性声明
};

Singleton * Singleton::instance_; //定义性声明

int main(void)
{
Singleton *s1 = Singleton::GetInstance();
Singleton *s2 = Singleton::GetInstance(); //s2的地址等于s1,即指向同一对象

//Singleton s3(*s1); //既然是单例模式,是不允许被拷贝的。编译会出错

return 0;
}

        上面就是单例类模式的C++实现,但是上述代码还有一个缺陷:单例类中申请的一些资源没有被释放,如instance_指向的空间没有被回收。一共有两种解决方式:
        第一种解决方式:

        

class Singleton
{
...
//提供一个回收接口,在应用中显示调用回收资源
static void Free()
{
delete instance_;
}

....
};

int main()
{
...
Singleton::Free(); //要显示调用进行资源回收
}
        这种方式虽然能实现功能,但是不太方便,每次都要手动回收资源,这是它的缺点。
        第二种解决方式:

class Singleton
{
...
public:
class Garbo //资源回收机制
{
public:
~Garbo()
{
if( Singleton::instance_ != NULL )
{
delete instance_;
}
}
};

...
private:
...
static Garbo garbo_; //引用性声明
};

Singleton::Garbo Singleton::garbo_;//定义性声明
        这种方式提供的处理方式显然要比第一种方式来的要便捷,因为它依靠内部提供的Garbo嵌套类来提供服务,当Singleton类生命周期结束时,Garbo的类对象garbo_也要销毁,它将调用析构函数,而在析构函数中又自动地释放了Singleton单例类申请的一些资源,这种实现就比较智能化。不需要手动释放资源。这是它的优势。
        

        下面提供另一种实现C++单例类模式的方法:

class Singleton
{
public:
static Singleton& GetInstance()
{
static Singleton instance_; return instance_;
}

~Singleton()
{
cout << "~Singleton"<<endl;
}
private:

Singleton()
{
cout << "Singleton "<<endl;
}
Singleton(const Singleton &other);
Singleton & operator=(const Singleton &other);
};
        这种实现方式利用了static修改函数内部的变量,当第一次调用GetInstance函数时,系统将构造一个Singleton对象,在后续再次调用这个函数时,系统不再执行这个语句,也就不会再构造Singleton类对象了,而直接返回instance_本身。另外,当Singleton类对象生命周期结束时,对象会自动调用析构函数销毁,这里也就不存在申请资源之类的了,需要注意的是GetInstance()函数返回的是引用,这样就不会调用拷贝构造函数了,使用时也应该声明Singleton的引用,如下:
       

int main()
{
Singleton &s1 = Singleton::GetInstance();
Singleton &s2 = Singleton::GetInstance(); //s1与s2是同一对象的引用

return 0;
}

---------------------
作者:ab198604
来源:CSDN
原文:https://blog.csdn.net/ab198604/article/details/19196315
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-04-22 15:19  damoying  阅读(194)  评论(0编辑  收藏  举报