您的位置:首页 > 职场人生

剑指Offer算法题之设计模式的单例模式--面试题2:实现Singleton模式

2017-07-12 10:09 381 查看
####提到单例模式,不得不稍微了解一下设计模式,所以首先介绍几种常见的设计模式。

设计模式:它表示了一个特定环境、一类问题和一个解决方案之间的关系。每一个模式都描述了一个不断重复发生的问题,以及该问题解决方案的核心设计。

常见设计模式介绍

1. 单例模式的介绍(singleton)

有些时候,允许自由创建某类的实例是会造成系统性能的下降。如果一个类始终只创建一个实例,则这个类就被称为单例类,这种模式就被称为单例模式。

核心思想:一个类只能创建一个对象

2.简单工厂模式的介绍

简单工厂模式是通过专门定义一个类来负责创建其它类的实例,被创建的实例通常都具有共同的父类。

核心思想:有一个专门的类来负责创建实例的过程。

有关单例模式,还有一些需要介绍的东西。对于系统中的某个类来说,只有一个实例是很重要的。例如一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;在Windows中就只能打开一个任务管理器。如果不对窗口对象进行唯一化,将弹出多个窗口,这些窗口弹出的对象一致的话,则是重复对象,浪费内存资源,若内容不一致,则表示系统状态与实际不符,会产生用户的误解。因此在特定的场景之下,使用单例模式是必须的选择。

如何实现单例模式:

因为单例模式是设计模式里唯一一种可以用几十行代码完整实现的模式,下面介绍一下单例模式的实现方式。

原理:如何保证一个类只有一个实例化的对象呢?定义一个全局变量可以确保对象可以随时都可以被访问,但是怎么限制只能实例化一个对象呢。下面我们把实现单例模式的思路说一下:

1、 因为单例模式是限制只能实例化的一个对象,也就是说在类外是不允许随意访问构造函数的。因此需要将类的构造函数设置为私有(private)或者保护(protected)类型。这样在类外定义的类就不能随意的实例化对象了。

class CFather
{
private:
//无参构造函数
CFather()
{
}
}


2、既然不能通过外部创建对象去调用构造函数进行实例化,那么我们可以通过静态成员函数进行类外调用,因为静态成员函数还可以通过类名作用域创建对象。因此我们只要在类内定义一个公共的静态成员函数,这样在类外就可以通过类名作用域进行调用函数。并在函数里面进行构造对象,因为是在类内,所以是可以构造的。

简单来说:1. 类内定义静态成员函数 2.类外用类名作用域调用函数 3. 函数里面返回类内的创建对象 4. 同类里可以调用私有的构造函数,完成对象实例化。

static CFather* CreatOJ()
{
//返回操作:通过私有的构造函数,创建一个对象操作
return (new CFather)
}
int main()
{
//类外静态成员函数可以通过类名作用域去调用
CFather *pf1=CFather::CreatOJ();
}


3、如何把实例化对象的个数限制在一个,是这里需要处理的过程。创建一个标识符,也是使用静态成员数据,类内声明,内外初始化。然后创建一个对象后就修改标识符,然后进行判断,以后都不允许进行对象实例化了。

class CFather
{
//类内申明
static int flag;
}
//类外初始化,也要通过类名作用域。
int CFather::flag=1;


4、 如何在第一个对象释放过后,允许下一个单例对象创建。就是在析构函数里去修改标识符。

public:
~CFather()
{
flag=1;
}


注意:以上给出的例子是一个无参的构造函数,为了实现一个完整的单例模式的构造方式,我们还需要添加:

1. 有参构造函数

2. 拷贝构造函数

3. 赋值构造函数(‘=’重载函数)

完整的单例模式构造代码如下:

#include <iostream>
using namespace std;
class CFather
{
//私有类型是不能够类外调用的,对外不可见
private:
//无参构造函数
CFather()
{

}
//有参构造函数
CFather(int a)
{

}
//拷贝构造函数
CFather(const CFather&a)
{

}
//赋值函数构造函数,也就是'='的重载
CFather& operator=(CFather &a)
{

}
//创建静态对象,从内部调用,可以在类外用类名作用域调用
public:
static int flag;
static CFather* CreatOJ()
{
if(flag==1)
{
flag=0;
return (new CFather);
}
else
return NULL;
}
//析构函数中重置标志位
public:
~CFather()
{
flag=<
4000
span class="hljs-number">1;
}
};
int CFather::flag=1;
int main()
{
CFather *pf1=CFather::CreatOJ();
delete pf1;
CFather *pf2=CFather::CreatOJ();
delete pf2;
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式 c++ 算法