文档章节

python 与设计模式 ——工厂与单例

duoduo3_69
 duoduo3_69
发布于 2013/11/27 11:19
字数 1070
阅读 885
收藏 14

python 与设计模式

源码地址:http://git.oschina.net/duoduo3_69/python_design_pattern

git checkout v001(这个版本与此篇博客相符)

zarkpy里面运用了很多设计模式,以前一直很费解python是怎么应用 设计模式的,他没有接口,也不是编译行的语言。直到sdjl(zarkpy 的原创者)对我说:

设计模式只是参考,重要的是自己写一些东西。

学习的过程中有一些思考,因此记录在这里。

这些原理性的东西也可以运用到别的一些动态语言中去,javascript 则有一本《JavaScript设计模式》可以参考。

Dao

dao/*.py

如果你熟悉java,自然会知道java里面有dao这个模式(Data Access Object), 继承自dao的类有数据库交互的能力。

对于python来说,你可以把dao命名为model(Django)等别的名字。

dao这个类应该是单例的,它类似于一个工具类,想象一下,如果有个User 类,你可能需要对user对象进行get,insert,delete,remove(增删改查), 这时是user对象与数据库之间的交互(把user这条记录扔到数据库里), user对象的状态在交互过程中是不应该改变的。

# -*- coding: utf-8 -*-
class Dao(object):
    """docstring for BaseDao"""
    def __init__(self):
        super(Dao, self).__init__()

    def get(self,item_id):
        """docstring for get"""
        pass

    def insert(self,data):
        """docstring for get"""
        pass

    def delete(self,item_id):
        """docstring for get"""
        pass

    def update(self,item_id,data):
        """docstring for get"""
        pass

User继承自Dao

# -*- coding: utf-8 -*-

from Dao import Dao

class User(Dao):
    """docstring for User"""
    def __init__(self):
        super(User, self).__init__()

单例模式实际上就是使用缓存。

java中使用static这种类加载的方式,将对象缓存在这里, 在编译执行的时 候确保对象是真正的单例。

public class Singleton {
    private static Singleton uniqueInstance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
       return uniqueInstance;
    }

}   

约定优于配置

rail 里面有句话是这样说的,约定优于配置(当然java也有这些东西, 想象下每个java bean里面那一堆getter setter吧,可以试试lombok), 在python里面可以使用工厂模式加缓存的方法,实现单例, 具体请看DaoFactory的实现方式,这里还用到了python里面模块加载 的一些技巧,参见helper.py与dao/init.py。

helper.py

# -*- coding: utf-8 -*-

import os,sys,glob

# 获得一个文件夹下所有的module,主要用于__init__.py文件自动import所有class
def getDirModules(dir_path, dir_name, except_files=None):
    if not except_files:except_files = []
    assert(os.path.exists(dir_path))
    ret_modules = []
    for file_path in glob.glob(dir_path+'/*.py'):
        file_name = file_path.rpartition('/')[2].rpartition('.')[0]
        if file_name not in except_files:
            __import__(dir_name.strip('.') + '.' + file_name)
            if file_name in dir(getattr(sys.modules[dir_name.strip('.')], file_name)):
                ret_modules.append((file_name, getattr(getattr(sys.modules[dir_name.strip('.')], file_name), file_name)))
    return ret_modules

dao/init.py #coding=utf-8 import os import helper # ../helper.py

EXCEPT_FILES = ['__init__']
for module_name, module in helper.getDirModules(os.path.split(os.path.realpath(__file__))[0], __name__, except_files=EXCEPT_FILES):
        exec('%s = module' % module_name)

工厂模式

DaoFactory.py

为什么要使用工厂模式呢?为了解放生产力,减少一堆'import XXX,m = XXX()'等 代码的编写吧。对于java来说则是new的操作。

工厂模式就是可以通过传进来的字符串参数来生成对象,当然可以创建 不同的工厂来满足不同的需求,例如对于dao模块我创建了一个工厂是 dao_factory,结合缓存实现了单例,这样用户在调用的时候每次生成的 就会是同一个对象。

ipython -i DaoFactory.py

u1 = dao_factory("User")
u2 = dao_factory("User")

u1 == u2 # True

工厂加缓存实现的单例模式,应该就是spring所做的事情(笔者并没有 看spring 的源码,猜测)。

DaoFactory.py,

# -*- coding: utf-8 -*-

import sys

CACHED_DAO = {}

def dao_factory(dao_name):
    """docstring for dao_factory"""
    assert isinstance(dao_name,(str,unicode))
    cache_key = dao_name

    if CACHED_DAO.has_key(cache_key):
        return CACHED_DAO[cache_key]

    else:
        import dao
        try:
            assert(hasattr(sys.modules["dao"],cache_key))
            dao = getattr(sys.modules["dao"],cache_key)
            dao = dao()
        except:
            print 'dao name is',cache_key
            raise

        CACHED_DAO[cache_key] = dao
        return dao

下面的代码块用到了helper.py以及dao/init.py里面的小技巧,当导入dao模块的时候,会执行__init__.py里面的方法块,它会将这个模块下的所有模块import进来,使得dao模块拥有一些属性,可以在交互模式尝试dir(dao)来看看

    import dao
        try:
            assert(hasattr(sys.modules["dao"],cache_key))
            dao = getattr(sys.modules["dao"],cache_key)
            dao = dao()

巨大的ps:希望能一起写issue

[开源项目]skill_issues——开发经验,要的就是干货

© 著作权归作者所有

duoduo3_69
粉丝 90
博文 57
码字总数 83746
作品 0
青岛
程序员
私信 提问
从 Java 到 Scala (三): object 的应用

本文由 Captain 发表在 ScalaCool 团队博客。 在上篇 Java 到 Scala 系列中,我想你或多或少在语言特性上对有了一定的掌握,在了解完它酷酷的语言特性——让静态回归常态并能简单运用其衍生出...

ScalaCool
2018/09/10
0
0
Java 中的 GoF 设计模式(第一部分)

为了理解 GoF(Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人组)的设计模式原理和历史,我制作了一个 10 分钟的短视频。(作为 PluralSight 作者试录的) 视频:https...

王桥修道院副院长
2017/02/13
2.7K
3
python 与设计模式 ——工厂与装饰者

python 与设计模式第二篇 添加了test.py,里面的单元测试有使用的方法。 源码地址:[http://git.oschina.net/duoduo3_69/python_design_pattern][1] git checkout v002(这个版本与此篇博客相符...

duoduo3_69
2013/11/27
241
1
大意了,这几道Python面试题没有答对,Python面试题No13

第1题: Python如何爬取 HTTPS 网站? 这类问题属于简单类问题 在使用 requests 前加入:requests.packages.urllib3.disable_warnings()。 为 requests 添加 verify=False 参数 导入ssl模块 ...

梦想橡皮擦
05/21
0
0
编程中的那些套路——关于单例模式

该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 在设计模式中,单例模式和工厂模式)可以说是使用的最普遍的设计模式了,所以掌握此种模式尤为重要。 单...

gzchen
2018/08/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Unable to connect to the server: x509: certificate signed by unknown authority

一、问题 当kubeadm安装完k8s后,使用kubectl命令,提示Unable to connect to the server: x509: certificate signed by unknown authority。 二、 解决 配置用户使用kubectl访问集群 $ mkdi...

人中泰迪
51分钟前
5
0
SpringBoot设置项目访问路径

今天配置Springboot项目访问路径遇到一个小坑,这里做一个记录。针对Springboot2.0以下版本和以上版本的配置方式是不同的。这里针对yml配置文件做记录,properties文件配置方式相同。 Spring...

王子城
56分钟前
7
0
Redis 序列化方式StringRedisSerializer、FastJsonRedisSerializer和KryoRedisSerializer

当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedis...

xiaolyuh
今天
5
0
jquery通过css的color属性实现选取特殊颜色的内容

今天一个朋友问到怎么使用jQuery选取特定颜色的内容,以前没有遇到过这样的需求。首先,很多人可能想到使用jQuery属性选择器来实现,这是不可以的,因为 color 是 css 的属性,而不是 html 的...

前端老手
今天
3
0
python3 网络爬虫开发实战 win10环境下 图形验证码识别需要安装的工具及地址

先下载安装tesseract exe文件 tesseract exe文件安装下载地址:https://digi.bib.uni-mannheim.de/tesseract/ win下直接下载双击安装即可,注意路径,下面用于配置环境变量。 参考网址: ht...

S三少S
今天
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部