前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式:单例模式

设计模式:单例模式

作者头像
王强
发布2018-08-09 18:02:56
3030
发布2018-08-09 18:02:56
举报
文章被收录于专栏:Python爬虫实战

1 概述

想想一下这个场景,一个系统中可以存在多个打印任务,但是只有一个正在工作的任务。我们怎样才能保证一个类只有一个实例并且这个实例易于被访问呢?一个全局变量可以使得一个对象可以被访问,但是不能防止实例化多个对象。

一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个方位该实例的方法,这就是单例模式的动机。

单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个 系统提供这个实例,这个类称为单例类,它提供全局访问的方法 。单例模式又名单件模式单态模式

单例模式的要点:

  • 某个类只能有一个实例
  • 它必须自行创建这个实例
  • 它必须自行向整个系统提供这个实例。

2 图解

此模式太简单,没有图。

单例模式包含如下角色:

  • Singleton:单例

3 优缺点

优点:

  • 提供了对唯一实例的受控访问。
  • 缩小命名空间。Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的 全局变量污染名空间。
  • 由于只存在一个实例,可以节约系统资源。
  • 允许可变数量的实例。

缺点:

  • 没有抽象层,拓展会有很大困难。
  • 单例类职责过重,在一定程度上违背了“单一原则”。

4 应用场景

在以下情况下可以使用抽象工厂模式:

  • 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
  • 系统中有多于一个的产品族,而每次只使用其中某一产品族。
  • 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
  • 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

5 实例

Singleton_Uml

5.1 C++实现

  • singleton.h
代码语言:javascript
复制
#ifndef SINGLETON_H
#define SINGLETON_H

#include <iostream>
using namespace std;

class Singleton
{
protected:
    Singleton();

public:
    static Singleton* Instance();

private:
    static Singleton* _instance;
};

#endif // SINGLETON_H
  • singleton.cpp
代码语言:javascript
复制
#include "singleton.h"
#include <iostream>

using namespace std;

Singleton* Singleton::_instance = 0;

Singleton::Singleton()
{
    cout << "==> Singleton." << endl;
}

Singleton* Singleton::Instance()
{
    if (_instance == 0)
    {
        _instance = new Singleton();
    }

    return _instance;
}
  • main.cpp
代码语言:javascript
复制
#include "singleton.h"
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    Singleton* singleton1 = Singleton::Instance();
    Singleton* singleton2 = Singleton::Instance();

    if (singleton1 == singleton2)
        cout << "They equal." << endl;
    return 0;
}

运行结果:

代码语言:javascript
复制
==> Singleton.
They equal.

代码说明:

客户仅通过 Instance() 成员函数访问这个单例。变量 _instance 初始化为0,而静态成员函数 Instance() 使用惰性初始化;它的返回值直到被第一次访问时才创建和保存。

注意构造器是保护型的。试图直接实例化 Singleton 的客户将得到一个编译时的错误信息。 这就保证了仅有一个实例可以被创建。 比如,我们使用如下代码实例化:

代码语言:javascript
复制
 Singleton* singleton = new Singleton();

编译器会报出如下错误:

代码语言:javascript
复制
E:\Programming\Design Patterns\Code\C++\04_Singleton\singleton.h:10: error: 'Singleton::Singleton()' is protected
     Singleton();
     ^

5.2 Python代码

代码语言:javascript
复制
#-*- coding: utf-8 -*-

'''
  单例模式
'''
class Singleton(object):
    _instance = None       

    def __new__(cls, *args, **kw):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)  
            print('==>Singleton')
        return cls._instance  

def main():
    singleton1 = Singleton()
    singleton2 = Singleton()
    print(singleton1 is singleton2)

if __name__ == '__main__':
    main()

运行结果:

代码语言:javascript
复制
==>Singleton
True

代码分析:

在上面的代码中,我们将类的实例和一个类变量 _instance 关联起来,如果 cls._instance 为 None 则创建实例,否则直接返回 cls._instance。最后print(singleton1 is singleton2)结果为Ture,说明singleton1与singleton2为同一实例。

系列推荐阅读:

  • 设计模式:简单工厂模式
  • 设计模式:工厂方法模式
  • 设计模式:抽象工厂模式
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 C与Python实战 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 概述
  • 2 图解
  • 3 优缺点
  • 4 应用场景
  • 5 实例
    • 5.1 C++实现
      • 5.2 Python代码
      相关产品与服务
      腾讯云代码分析
      腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档