欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Tornado中的单例模式(Singleton)

程序员文章站 2022-06-14 18:50:38
...
单例模式也是设计模式一书中介绍的23中设计模式之一。
Questions:
  • 1、@classmethod和@staticmethod 的用法与区别?
  • 2、Singleton的实现
  • 3、Singleton什么时候适合使用?

问题1、
引用

     A staticmethod is a method that knows nothing about the class or instance it was called on. It just gets the arguments that were passed, no implicit first argument. It is basically useless in Python -- you can just use a module function instead of a staticmethod.
     A classmethod, on the other hand, is a method that gets passed the class it was called on, or the class of the instance it was called on, as first argument. This is useful when you want the method to be a factory for the class: since it gets the actual class it was called on as first argument, you can always instantiate the right class, even when subclasses are involved. Observe for instance howdict.fromkeys(), a classmethod, returns an instance of the subclass when called on a subclass:

示例:
#!/usr/bin/env python
#-*-encoding:utf-8-*-
class Demo:

    def get(self,x):
        print 'self and x is (%s,%s)'%(self,x)

    @classmethod
    def instance(cls,x):
        print 'cls and x Is (%s,%s)'%(cls,x)

    @staticmethod
    def static(x):
        print 'self and x is %s'%x

def main():
    demo = Demo()
    x=1
    demo.get(x)
    demo.instance(x)
    demo.static(x)
    Demo.instance(x)
    Demo.static(x)

if __name__=="__main__":
    main()

Result:

self and x is (<__main__.Demo instance at 0x109d44680>,1)
cls and x Is (__main__.Demo,1)
x is 1
cls and x Is (__main__.Demo,1)
x is 1

引用

     Below is the usual way an object instance calls a method. The object instance, a, is implicitly passed as the first argument.
     With classmethods, the class of the object instance is implicitly passed as the first argument instead ofself.
     With staticmethods, neither self (the object instance) nor cls (the class) is implicitly passed as the first argument.

    @staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.
    @classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance. That’s because the first argument for @classmethod function must always be cls (class).


classmethod可以通过类实例调用,staticmethod只能通过类名调用

Say function a() is defined in Parent Class, while Sub Class extends Parent Class
If function a() has @staticmethod decorator, Sub.a() still refers to definition inside Parent Class. Whereas,
If function a() has @classmethod decorator, Sub.a() will points definition inside Sub Class.
继承的时候staticmethod调用的是父类的方法
classmethod由于传入了cls,父类和子类是加以区分开的

问题2、
我们先看下tornado源码中的单例模式。
    @staticmethod
    def instance():
        """Returns a global IOLoop instance.
        Most single-threaded applications have a single, global IOLoop.
        Use this method instead of passing around IOLoop instances
        throughout your code.
        A common pattern for classes that depend on IOLoops is to use
        a default argument to enable programs with multiple IOLoops
        but not require the argument for simpler applications::
            class MyClass(object):

                def __init__(self, io_loop=None):

                    self.io_loop = io_loop or IOLoop.instance()
        """
        if not hasattr(IOLoop, "_instance"):
            with IOLoop._instance_lock:
                if not hasattr(IOLoop, "_instance"):
                    # New instance after double check
                    IOLoop._instance = IOLoop()
        return IOLoop._instance

    @staticmethod
    def initialized():
        """Returns true if the singleton instance has been created."""
        return hasattr(IOLoop, "_instance")

    def install(self):
        """Installs this IOloop object as the singleton instance.
        This is normally not necessary as `instance()` will create
        an IOLoop on demand, but you may want to call `install` to use
        a custom subclass of IOLoop.
        """
        assert not IOLoop.initialized()
        IOLoop._instance = self



demo示例:
class Demo(object):

    def __init__(self):
        pass

    @classmethod
    def instance(cls):
        if not hasattr(cls,'_instance'):
            cls._instance=cls()
        return cls._instance

    @staticmethod
    def static_instance():
        if not hasattr(Demo,'_instance'):
            Demo._instance=Demo()
        return Demo._instance

    def test(self):
        print 'This is a demo.'

class MiniDemo(Demo):


    def __init__(self):
        super(MiniDemo, self).__init__()

    def test(self):
        print 'A new story.'

MiniDemo.instance().test()
MiniDemo.static_instance().test()
Demo.instance().test()
Demo.static_instance().test()


A new story.
This is a demo.
This is a demo.
This is a demo.


问题3、

请思考?适用场景以及局限。

单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。
class Singleton

{
     private static Singleton instance;
     private Singleton()
     {

     }
     public static Singleton GetInstance()
     {
          if(instance == null)
          {
               instance = new Singleton();
          }
          return instance;
     }
}

作为其他对象的雏形而存在的对象,以及系统全体只存在唯一一个的对象等,都要用到Singleton模式。

Others:

  • with
  • super的用法
  • threading.local()


参考资料:
https://fuhm.net/super-harmful/
http://docs.python.org/2/library/functions.html#super
http://docs.python.org/2/library/functions.html#classmethod
http://docs.python.org/2/library/functions.html#staticmethod
http://www.artima.com/weblogs/viewpost.jsp?thread=236275
http://apt-blog.net/constructors_with_different_arguments_in_python_multiinheri_class
http://*.com/questions/8972866/correct-way-to-use-super-argument-passing
http://*.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python