<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>设计模式 | Hugo Academic Blog Theme</title><link>https://blog.xuzhaoyang.fun/category/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/</link><atom:link href="https://blog.xuzhaoyang.fun/category/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/index.xml" rel="self" type="application/rss+xml"/><description>设计模式</description><generator>Wowchemy (https://wowchemy.com)</generator><language>en-us</language><lastBuildDate>Tue, 05 Mar 2019 17:10:02 +0000</lastBuildDate><image><url>https://blog.xuzhaoyang.fun/media/icon_hua2ec155b4296a9c9791d015323e16eb5_11927_512x512_fill_lanczos_center_3.png</url><title>设计模式</title><link>https://blog.xuzhaoyang.fun/category/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/</link></image><item><title>Python 设计模式 - 单例模式</title><link>https://blog.xuzhaoyang.fun/post/python-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/</link><pubDate>Tue, 05 Mar 2019 17:10:02 +0000</pubDate><guid>https://blog.xuzhaoyang.fun/post/python-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/</guid><description>&lt;p>单例模式是一种比较常见的设计模式，所以顺理成章的成为我们第一个介绍的设计模式。
应用场景：&lt;/p>
&lt;ul>
&lt;li>资源共享。例如，数据库连接，配置管理，日志管理。&lt;/li>
&lt;/ul>
&lt;p>实现方法有多种：&lt;/p>
&lt;!-- more -->
&lt;ul>
&lt;li>使用**_&lt;em>new&lt;/em>_**&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-python">class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls) #这里需要注意不能使用cls(), 否则会导致无限递归
return cls._instance
ins1 = Singleton()
ins2 = Singleton()
id(ins1) == id(ins2) # True
&lt;/code>&lt;/pre>
&lt;ul>
&lt;li>使用闭包/函数装饰器&lt;/li>
&lt;/ul>
&lt;p>闭包使得自由变量&lt;strong>instance&lt;/strong>在**_singleton**调用完成后没有被释放，跟上诉方法中的类变量作用一样。&lt;/p>
&lt;pre>&lt;code class="language-python">from functools import wraps
def _singleton(cls):
instance = {}
@wraps(cls)
def func(*args,**kwargs):
if cls not in instance:
instance[cls] = cls(*args,**kwargs)
return instance[cls]
return func
@_singleton
class Singleton:
pass
ins1 = Singleton()
ins2 = Singleton()
id(ins1) == id(ins2) # True
&lt;/code>&lt;/pre>
&lt;ul>
&lt;li>使用类装饰器
是的装饰器除了函数也可以说是类，在类作为装饰器时，会调用类的**__call__**方法&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-python">class GenSingleton:
def __init__(self, cls):
&amp;quot;&amp;quot;&amp;quot;
在编译时会调用该方法
&amp;quot;&amp;quot;&amp;quot;
self._cls = cls
self._instance = {}
def __call__(self, *args, **kwargs):
&amp;quot;&amp;quot;&amp;quot;
在实例化类时调用该方法
&amp;quot;&amp;quot;&amp;quot;
if self._cls not in self._instance:
self._instance[self._cls] = self._cls(*args, **kwargs)
return self._instance[self._cls]
@GenSingleton
class Singleton:
pass
s1 = Singleton()
s2 = Singleton()
print(id(s1) == id(s2)) # True
&lt;/code>&lt;/pre>
&lt;ul>
&lt;li>使用metaclass&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-python">class SingletonType(type):
def __init__(cls, *args, **kwargs):
&amp;quot;&amp;quot;&amp;quot;
在编译时调用该方法
&amp;quot;&amp;quot;&amp;quot;
cls._instance = None
def __call__(cls, *args, **kwargs):
&amp;quot;&amp;quot;&amp;quot;
在实例化类时调用该方法
&amp;quot;&amp;quot;&amp;quot;
if cls._instance is None:
cls._instance = super().__call__(*args, **kwargs)
return cls._instance
class Singleton(metaclass=SingletonType):
pass
s1 = Singleton()
s2 = Singleton()
print(id(s1) == id(s2)) # True
&lt;/code>&lt;/pre>
&lt;p>对于Python引入机制熟悉的同学应该知道Python中的模块只会import一次，所以算是天然的单例模式。当然究其原因是在第一次import时会生成pyc文件，以后import时会直接读取pyc内容。&lt;/p>
&lt;ul>
&lt;li>使用模块&lt;/li>
&lt;/ul>
&lt;p>singleton.py&lt;/p>
&lt;pre>&lt;code class="language-python">class Singleton:
pass
s = Singleton()
&lt;/code>&lt;/pre>
&lt;p>usage.py&lt;/p>
&lt;pre>&lt;code class="language-python">from singleton import s as s1
from singleton import s as s2
print(id(s1) == id(s2)) # True
&lt;/code>&lt;/pre>
&lt;p>当然实现方式还有不少，但实质上差别不大，我们平时使用的时候掌握其中之一即可。&lt;/p></description></item></channel></rss>