全国咨询/投诉热线:400-618-9090

首页技术文章正文

元类实现单例模式

更新时间:2018-07-13 11:44:09.0 来源:黑马程序员JavaEE培训学院

Python中的类也是对象。元类就是用来创建这些类(对象)的,元类就是类的类,你可以这样理解为:
MyClass = MetaClass()    #元类创建
MyObject = MyClass()     #类创建实例

实际上MyClass就是通过type()来创创建出MyClass类,它是type()类的一个实例;同时MyClass本身也是类,也可以创建出自己的实例,这里就是MyObject
函数type实际上是一个元类。type就是Python在背后用来创建所有类的元类。现在你想知道那为什么type会全部采用小写形式而不是Type呢?好吧,我猜这是为了和str保持一致性,str是用来创建字符串对象的类,而int是用来创建整数对象的类。type就是创建类对象的类。你可以通过检查__class__属性来看到这一点。Python中所有的东西,注意,我是指所有的东西——都是对象。这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来。
那什么是单例呢?为什么我们要用单例设计模式?
我们首先来看看单例模式的使用场景,然后再来分析为什么需要单例模式。
        •        Python的logger就是一个单例模式,用以日志记录
        •        Windows的资源管理器是一个单例模式
        •        线程池,数据库连接池等资源池一般也用单例模式
        •        网站计数器
从这些使用场景我们可以总结下什么情况下需要单例模式:
        1.        当每个实例都会占用资源,而且实例初始化会影响性能,这个时候就可以考虑使用单例模式,它给我们带来的好处是只有一个实例占用资源,并且只需初始化一次;
        2.        当有同步需要的时候,可以通过一个实例来进行同步控制,比如对某个共享文件(如日志文件)的控制,对计数器的同步控制等,这种情况下由于只有一个实例,所以不用担心同步问题。
那什么是单例呢?为什么我们要用单例设计模式?
我们首先来看看单例模式的使用场景,然后再来分析为什么需要单例模式。
        •        Python的logger就是一个单例模式,用以日志记录
        •        Windows的资源管理器是一个单例模式
        •        线程池,数据库连接池等资源池一般也用单例模式
        •        网站计数器
从这些使用场景我们可以总结下什么情况下需要单例模式:
        1.        当每个实例都会占用资源,而且实例初始化会影响性能,这个时候就可以考虑使用单例模式,它给我们带来的好处是只有一个实例占用资源,并且只需初始化一次;
        2.        当有同步需要的时候,可以通过一个实例来进行同步控制,比如对某个共享文件(如日志文件)的控制,对计数器的同步控制等,这种情况下由于只有一个实例,所以不用担心同步问题。

在python中实现单例模式有几种方法:

        1. 使用模块
        2. 使用装饰器
        3. 使用类
        4. 基于__new__方法实现(推荐使用,方便)
        5. 基于metaclass元类方式实现
这里说说基于元类来实现。代码如下:

class Singleton(type):
    def __init__(cls, name, bases, dic):
        print('元类的__init__方法在被执行')
        super(Singleton, cls).__init__(name, bases, dic)
        cls.instance = None

    def __call__(cls, *args, **kwargs):
        if not cls.instance:
            print('创建一个新对象')
            cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
        else:
            print('单例,只能创建一个对象')

        return cls.instance

class A(metaclass=Singleton):

    # __metaclass__ = Singleton
    pass  # python3 取消了__metaclass__属性

a = A()
b = A()
print(a is b)
print(A.__dict__)

元类的__init__方法在被执行
创建一个新对象
单例,只能创建一个对象

True
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None, 'instance': <__main__.A object at 0x1027c5cf8>}

本文版权归黑马程序员JavaEE学院所有,欢迎转载,转载请注明作者出处。谢谢!

作者:黑马程序员JavaEE培训学院

首发:http://java.itheima.com/

在线咨询 我要报名