Python版设计模式: 创建型模式:单例模式和工厂模式家族
一. 单例模式(Singleton
)
所谓单例模式,也就是说不管什么时候都要确保只有一个对象实例存在。很多情况下,整个系统中只需要存在一个对象,所有的信息都从这个对象获取,比如系统的配置对象,或者是线程池。这些场景下,就非常适合使用单例模式。
总结起来,就是说不管初始化一个对象多少次,真正干活的对象只会生成一次并且在首次生成。
用Python 实现单例模式的方法有很多,先来看第一种方式。
# !/usr/bin/python3
# -*- coding:utf-8 -*- class singleton(object):
"""
单列模式
""" class _A(object):
"""
真正干活的类,对外隐藏。
""" def __init__(self):
pass def display(self):
""" 返回当前实例的ID,是全局唯一的"""
return id(self) # 类变量,用于存储_A 的实例
_instance = None def __init__(self):
""" 先判断类变量中是否已经保存了_A 的实例,如果没有则创建一个后返回"""
if singleton._instance is None:
singleton._instance = singleton._A() def __getattr__(self, attr):
return getattr(self._instance, attr) if __name__ == "__main__":
# 创建2个实例
s1 = singleton()
s2 = singleton()
print(id(s1), s1.display())
print(id(s2), s2.display())
# !/usr/bin/python3 # -*- coding:utf-8 -*- class singleton(object): """ 单列模式 """ class _A(object): """ 真正干活的类,对外隐藏。 """ def __init__(self): pass def display(self): """ 返回当前实例的ID,是全局唯一的""" return id(self) # 类变量,用于存储_A 的实例 _instance = None def __init__(self): """ 先判断类变量中是否已经保存了_A 的实例,如果没有则创建一个后返回""" if singleton._instance is None: singleton._instance = singleton._A() def __getattr__(self, attr): return getattr(self._instance, attr) if __name__ == "__main__": # 创建2个实例 s1 = singleton() s2 = singleton() print(id(s1), s1.display()) print(id(s2), s2.display())
Output:
1917919737784 1917919737896
1917919738008 1917919737896
以上的单列模式实现中,借助了使用类变量 Singleton._instance 来存储创建的实例,并且保证只会创建一次实例。由于 Python 是一门动态语言,可以在运行时改变类定义。上面的代码中,在首次初始化 Singleton 时,将首次生成类 _A 的实例,并将其存储到 Singleton._instance 中,以后每次初始化 Singleton 时都从 Singleton._instance 获取真正干活的实例,这样就实现了单例模式。
从输出中可以看到,尽管创建了两个不同的实例(实例 ID 不同),但是访问其属性的时候得到的 ID 是一致的。以上代码虽然很好的实现了单例模式,但是在真正的项目开发中这种方式却不够灵活,因为要将真正干活的类内置在单例类中。 我们知道在 Python 中装饰器很好用,那能否将单例类实现成一个装饰器呢?答案是肯定的,下面实现代码。
# !/usr/bin/python3
# -*- coding:utf-8 -*-
import sqlite3
from flask import current_app
from flask import _app_ctx_stack as stack class SQLite3(object):
def __init__(self, app=None):
self.app = app
if app is not None:
self.init_app(app) def init_app(self, app):
"""典型的 Flask 扩展的初始化方式"""
app.config.setdefault('SQLITE3_DATABASE', ':memory:')
app.teardown_appcontext(self.teardown) def connect(self):
"""连接到 sqlite 数据库"""
return sqlite3.connect(current_app.config['SQLITE3_DATABASE']) def teardown(self, exception):
"""关闭 sqlite 链接"""
ctx = stack.top
if hasattr(ctx, 'sqlite3_db'):
ctx.sqlite3_db.close() @property
def connection(self):
"""
单例模式在这里:使用 flask._app_ctx_stack 存放 sqlite 链接,
每次获取数据库链接时都通过 connection 获取
"""
ctx = stack.top
if ctx is not None:
if not hasattr(ctx, 'sqlite3_db'):
ctx.sqlite3_db = self.connect()
return ctx.sqlite3_db
在以上的代码中,在每次使用数据库的时候通过 SQLite3.connection 获取数据库连接就可以了。SQLite3.connection保证了数据库连接只会发生一次,其原理和之前实现单例模式的方式相同,只不过这里存储实例的地方变成 flask._app_ctx_stack了。
通过以上几段代码,可以看到单例模式的实现只需要找一个变量存放创建的实例,然后每次获取实例时,先检查变量中是否已保存实例,如果没有则创建一个实例并将其存放到变量中,以后都从这个变量中获取实例就可以了。单例模式中,只会创建一次实例。
Python版设计模式: 创建型模式:单例模式和工厂模式家族的更多相关文章
- python设计模式---创建型之单例模式
数据结构和算法是基本功, 设计模式是最佳实现. 作为程序员,必须有空了就练一练哈. # coding = utf-8 """ # 经典单例 class Singleton ...
- java设计模式--创建型模式(一)
2016-04-24 10:10:34 创建型模式:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 注意:工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂 ...
- C#设计模式-创建型模式(转)
一.简单工厂模式 简单工厂模式Simple Factory,又称静态工厂方法模式.它是类的创建模式.是由一个工厂对象决定创建出哪一种产品类的实例,是不同的工厂方法模式的一个特殊实现. 优点: u 模式 ...
- 设计模式(三): FACTORY工厂模式 -- 创建型模式
1.定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到了子类. 2.适用场景 1.第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体 ...
- Java设计模式(3)——创建型模式之抽象工厂模式(Abstract Factory)
一.概述 抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式.抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象. UML图: 其他的过多概念不再 ...
- 设计模式----创建型模式之工厂模式(FactoryPattern)
工厂模式主要分为三种简单工厂模式.工厂方法模式.抽象工厂模式三种.顾名思义,工厂主要是生产产品,作为顾客或者商家,我们不考虑工厂内部是怎么一个流程,我们要的是最终产品.将该种思路放在我们面向对象开发实 ...
- java设计模式 -------- 创建模式 之 抽象工厂模式
本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 工厂方法模式和抽象工厂模式不好区分清楚: 工厂方法模式特点: 1. 一个抽象产品 ...
- python 设计模式之工厂模式 Factory Pattern (简单工厂模式,工厂方法模式,抽象工厂模式)
十一回了趟老家,十一前工作一大堆忙成了狗,十一回来后又积累了一大堆又 忙成了狗,今天刚好抽了一点空开始写工厂方法模式 我看了<Head First 设计模式>P109--P133 这25页 ...
- PHP面向对象-设计模式 单例模式 简单工厂模式 工厂方法模式
1.单例模式 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例.即一个类只有一个对象实例. 要实现每一个类只有一个实例,就需 ...
- [19/04/23-星期二] GOF23_创建型模式(工厂模式、抽象工厂模式)
一.工厂模式(分为:简单工厂模式.工厂方法模式.抽象工厂模式) 实现了创建者和调用者的分离 核心本质:1.实例化对象,用工厂方法代替new操作:2.将选择实现类.创建对象统一管理和控制,从而将调用者跟 ...
随机推荐
- USB设备(移动硬盘、鼠标)掉电掉驱动的两种解决方案
症状: 当你发现"移动硬盘图标"经常无故消失,又自己出现时. 你可以把这个现象称之为"掉电" or "掉驱动". 遇到这种情况,相当不爽. ...
- C# VLCPlayer视频播放器(附源码)
VLCPlayer视频播放器. 支持本地播放,支持网络URL.支持全屏,截图. 基于VLCPlayer. 附带基本代码. 下载地址:http://pan.baidu.com/s/1nvjNvID
- asp.net mvc View视图相关
1.0 @helper语法 @helper语法可以定义可重复使用的帮助器方法: 例如 @helper methodName(type paramName,...){ //todo } 调用:@meth ...
- 【WCF】如何将WCF部署到远程服务器
一.前言 最近需要将自己写的WCF服务部署到远程服务器上,也就是公网上.宿主是IIS,在配置成功之前遇到了很多问题,问题如下: 1. WCF该怎么宿主在IIS上,为何会出现 400 Bad ...
- Shell脚本编程30分钟入门
Shell脚本编程30分钟入门 转载地址: Shell脚本编程30分钟入门 什么是Shell脚本 示例 看个例子吧: #!/bin/sh cd ~ mkdir shell_tut cd shell_t ...
- EChart使用
EChart ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等 ...
- 【C#公共帮助类】 WebHelper帮助类
如果你是一个新手,如果你刚接触MVC,如果你跟着置顶的那个项目,我们肯定会用到这里面的几个帮助类 它们都在Common类库下,大家一定要记住要点:取其精华去其糟粕,切勿拿来主义~ Applicatio ...
- 脚本化CSS类-HTML5 classList属性
HTML元素可以有多个CSS类名,class属性保存了一个用空格隔开的类名列表.标识符class在JavaScript中是保留字,所以在JavaScript中可以用className. //如下代码设 ...
- Qt——组件位置随窗口变化
当我们用Qt Designer设计界面时,有时会面临这样一个问题:需要在窗口指定位置放置组件,并且当窗口位置大小改变时,该组件相对其父对象的位置是不变的,如下面两幅图所示 ,首先看上面这幅图,注意bu ...
- px、dp和sp,这些单位有什么区别?
DP 这个是最常用但也最难理解的尺寸单位.它与“像素密度”密切相关,所以 首先我们解释一下什么是像素密度.假设有一部手机,屏幕的物理尺寸为1.5英寸x2英寸,屏幕分辨率为240x320,则我们可以计算 ...