常见设计模式 (python代码实现)
1. 创建型模式
单例模式
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象
1 class Singleton(object): 2 def __init__(self): 3 pass 4 5 def __new__(cls, *args, **kwargs): 6 if not hasattr(Singleton, "_instance"): # 反射 7 Singleton._instance = object.__new__(cls) 8 return Singleton._instance 9 10 obj1 = Singleton() 11 obj2 = Singleton() 12 print(obj1, obj2) #<__main__.Singleton object at 0x004415F0> <__main__.Singleton object at 0x004415F0>
工厂模式
工厂模式是一个在软件开发中用来创建对象的设计模式。
工厂模式包涵一个超类。这个超类提供一个抽象化的接口来创建一个特定类型的对象,而不是决定哪个对象可以被创建。
为了实现此方法,需要创建一个工厂类创建并返回。
当程序运行输入一个“类型”的时候,需要创建于此相应的对象。这就用到了工厂模式。在如此情形中,实现代码基于工厂模式,可以达到可扩展,可维护的代码。当增加一个新的类型,不在需要修改已存在的类,只增加能够产生新类型的子类。
简短的说,当以下情形可以使用工厂模式:
1. 不知道用户想要创建什么样的对象
2. 当你想要创建一个可扩展的关联在创建类与支持创建对象的类之间。
一个例子更能很好的理解以上的内容:
- 我们有一个基类 Person ,包涵获取名字,性别的方法 。有两个子类 male 和 female,可以打招呼。还有一个工厂类。
- 工厂类有一个方法名 getPerson 有两个输入参数,名字和性别。
- 用户使用工厂类,通过调用 getPerson 方法。
在程序运行期间,用户传递性别给工厂,工厂创建一个与性别有关的对象。因此工厂类在运行期,决定了哪个对象应该被创建
class Person: def __init__(self): self.name = None self.gender = None</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> getName(self): </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> self.name </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> getGender(self): </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> self.gender
class Male(Person):
def init(self, name):
print "Hello Mr." + nameclass Female(Person):
def init(self, name):
print "Hello Miss." + nameclass Factory:
def getPerson(self, name, gender):
if gender == ‘M':
return Male(name)
if gender == 'F':
return Female(name)if name == 'main':
factory = Factory()
person = factory.getPerson("Chetan", "M")
建造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
相关模式:思路和模板方法模式很像,模板方法是封装算法流程,对某些细节,提供接口由子类修改,建造者模式更为高层一点,将所有细节都交由子类实现
一个例子更能很好的理解以上的内容:
1. 有一个接口类,定义创建对象的方法。一个指挥员类,接受创造者对象为参数。两个创造者类,创建对象方法相同,内部创建可自定义
2. 一个指挥员,两个创造者 (瘦子 胖子),指挥员可以指定由哪个创造者来创造
from abc import ABCMeta, abstractmethodclass Builder():
metaclass = ABCMeta@abstractmethod </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_left_arm(self): </span><span style="color: rgba(0, 0, 255, 1)">pass</span><span style="color: rgba(0, 0, 0, 1)"> @abstractmethod </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_right_arm(self): </span><span style="color: rgba(0, 0, 255, 1)">pass</span><span style="color: rgba(0, 0, 0, 1)"> @abstractmethod </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_left_foot(self): </span><span style="color: rgba(0, 0, 255, 1)">pass</span><span style="color: rgba(0, 0, 0, 1)"> @abstractmethod </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_right_foot(self): </span><span style="color: rgba(0, 0, 255, 1)">pass</span><span style="color: rgba(0, 0, 0, 1)"> @abstractmethod </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_head(self): </span><span style="color: rgba(0, 0, 255, 1)">pass</span><span style="color: rgba(0, 0, 0, 1)"> @abstractmethod </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_body(self): </span><span style="color: rgba(0, 0, 255, 1)">pass</span>
class Thin(Builder):
def draw_left_arm(self):
print '画左手'<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_right_arm(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">画右手</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_left_foot(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">画左脚</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_right_foot(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">画右脚</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_head(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">画头</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_body(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">画瘦身体</span><span style="color: rgba(128, 0, 0, 1)">'</span>
class Fat(Builder):
def draw_left_arm(self):
print '画左手'<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_right_arm(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">画右手</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_left_foot(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">画左脚</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_right_foot(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">画右脚</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_head(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">画头</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw_body(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">画胖身体</span><span style="color: rgba(128, 0, 0, 1)">'</span>
class Director():
def init(self, person):
self.person=person</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> draw(self): self.person.draw_left_arm() self.person.draw_right_arm() self.person.draw_left_foot() self.person.draw_right_foot() self.person.draw_head() self.person.draw_body()
if name=='main':
thin=Thin()
fat=Fat()
director_thin=Director(thin)
director_thin.draw()
director_fat=Director(fat)
director_fat.draw()
原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式本质就是克隆对象,所以在对象初始化操作比较复杂的情况下,很实用,能大大降低耗时,提高性能,因为“不用重新初始化对象,而是动态地获得对象运行时的状态”。
浅拷贝(Shallow Copy): 指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝的对象和源对象只是名称相同,但是他们共用一个实体。
深拷贝(deep copy): 对对象实例中字段引用的对象也进行拷贝。
import copy from collections import OrderedDictclass Book:
def init(self, name, authors, price, **rest):
'''rest 的例子有:出版商、长度、标签、出版日期'''
self.name = name
self.authors = authors
self.price = price # 单位为美元
self.dict.update(rest)</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__str__</span><span style="color: rgba(0, 0, 0, 1)">(self): mylist </span>=<span style="color: rgba(0, 0, 0, 1)"> [] ordered </span>= OrderedDict(sorted(self.<span style="color: rgba(128, 0, 128, 1)">__dict__</span><span style="color: rgba(0, 0, 0, 1)">.items())) </span><span style="color: rgba(0, 0, 255, 1)">for</span> i <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> ordered.keys(): mylist.append(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">{}: {}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">.format(i, ordered[i])) </span><span style="color: rgba(0, 0, 255, 1)">if</span> i == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">price</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">: mylist.append(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">$</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">) mylist.append(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">''</span><span style="color: rgba(0, 0, 0, 1)">.join(mylist)
class Prototype:
def init(self):
self.objects = dict()</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> register(self, identifier, obj): self.objects[identifier] </span>=<span style="color: rgba(0, 0, 0, 1)"> obj </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> unregister(self, identifier): </span><span style="color: rgba(0, 0, 255, 1)">del</span><span style="color: rgba(0, 0, 0, 1)"> self.objects[identifier] </span><span style="color: rgba(0, 0, 255, 1)">def</span> clone(self, identifier, **<span style="color: rgba(0, 0, 0, 1)">attr): found </span>=<span style="color: rgba(0, 0, 0, 1)"> self.objects.get(identifier) </span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(0, 0, 255, 1)">not</span><span style="color: rgba(0, 0, 0, 1)"> found: </span><span style="color: rgba(0, 0, 255, 1)">raise</span> ValueError(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Incorrect object identifier: {}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">.format(identifier)) obj </span>=<span style="color: rgba(0, 0, 0, 1)"> copy.deepcopy(found) obj.</span><span style="color: rgba(128, 0, 128, 1)">__dict__</span><span style="color: rgba(0, 0, 0, 1)">.update(attr) </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> obj
def main():
b1 = Book('The C Programming Language', ('Brian W. Kernighan', 'Dennis M.Ritchie'),
price=118, publisher='Prentice Hall', length=228, publication_date='1978-02-22',
tags=('C', 'programming', 'algorithms', 'data structures'))
prototype = Prototype()
cid = 'k&r-first'
prototype.register(cid, b1)
b2 = prototype.clone(cid, name='The C Programming Language(ANSI)', price=48.99,
length=274, publication_date='1988-04-01', edition=2)
for i in (b1, b2):
print(i)
print("ID b1 : {} != ID b2 : {}".format(id(b1), id(b2)))if name == 'main':
main()"""
>>> python3 prototype.py
authors: ('Brian W. Kernighan', 'Dennis M. Ritchie')
length: 228
name: The C Programming Language
price: 118$
publication_date: 1978-02-22
publisher: Prentice Hall
tags: ('C', 'programming', 'algorithms', 'data structures')authors: ('Brian W. Kernighan', 'Dennis M. Ritchie')
edition: 2
length: 274
name: The C Programming Language (ANSI)
price: 48.99$
publication_date: 1988-04-01
publisher: Prentice Hall
tags: ('C', 'programming', 'algorithms', 'data structures')ID b1 : 140004970829304 != ID b2 : 140004970829472
"""
2. 结构型模式
适配器模式
所谓适配器模式是指是一种接口适配技术,它可通过某个类来使用另一个接口与之不兼容的类,运用此模式,两个类的接口都无需改动。
适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,比如在需要对早期代码复用一些功能等应用上很有实际价值。
解释二:
适配器模式 (Adapter Pattern): 将一个类的接口转换成为客户希望的另外一个接口.Adapter Pattern 使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.
应用场景: 系统数据和行为都正确, 但接口不符合时, 目的是使控制范围之外的一个原有对象与某个接口匹配, 适配器模式主要应用于希望复用一些现存的类, 但接口又与复用环境不一致的情况
class Target(object): def request(self): print "普通请求"class Adaptee(object):
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> specific_request(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">特殊请求</span><span style="color: rgba(128, 0, 0, 1)">"</span>
class Adapter(Target):
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self): self.adaptee </span>=<span style="color: rgba(0, 0, 0, 1)"> Adaptee() </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> request(self): self.adaptee.specific_request()
if name == "main":
target = Adapter()
target.request()
修饰器模式
该模式虽名为修饰器,但这并不意味着它应该只用于让产品看起来更漂亮。修饰器模式通常用于扩展一个对象的功能。这类扩展的实际例子有,给枪加一个消音器、使用不同的照相机镜头
import functools def memoize(fn): known = dict()@functools.wraps(fn) def memoizer(*args): if args not in known: known[args] = fn(*args) return known[args] return memoizer @memoize def nsum(n): '''返回前 n 个数字的和''' assert(n >= 0), 'n must be >= 0' return 0 if n == 0 else n + nsum(n-1) @memoize def fibonacci(n): '''返回斐波那契数列的第 n 个数''' assert(n >= 0), 'n must be >= 0' return n if n in (0, 1) else fibonacci(n-1) + fibonacci(n-2) if __name__ == '__main__': from timeit import Timer measure = [ {'exec':'fibonacci(100)', 'import':'fibonacci', 'func':fibonacci},{'exec':'nsum(200)', 'import':'nsum', 'func':nsum} ] for m in measure: t = Timer('{}'.format(m['exec']), 'from __main__ import{}'.format(m['import'])) print('name: {}, doc: {}, executing: {}, time:{}'.format(m['func'].__name__, m['func'].__doc__,m['exec'], t.timeit()))"""
>>> python3 mymath.py
name: fibonacci, doc: Returns the nth number of the Fibonacci
sequence, executing: fibonacci(100), time: 0.4169441329995607
name: nsum, doc: Returns the sum of the first n numbers,
executing: nsum(200), time: 0.4160157349997462
"""
外观模式
外观模式又叫做门面模式。在面向对象程序设计中,解耦是一种推崇的理念。但事实上由于某些系统中过于复杂,从而增加了客户端与子系统之间的耦合度。例如:在家观看多媒体影院时,更希望按下一个按钮就能实现影碟机,电视,音响的协同工作,而不是说每个机器都要操作一遍。这种情况下可以采用外观模式,即引入一个类对子系统进行包装,让客户端与其进行交互。
外观模式 (Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。
from enum import Enum from abc import ABCMeta, abstractmethodState = Enum('State', 'new running sleeping restart zombie')
class User:
passclass Process:
passclass File:
passclass Server(metaclass=ABCMeta):
@abstractmethod
def init(self):
pass<span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__str__</span><span style="color: rgba(0, 0, 0, 1)">(self): </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> self.name @abstractmethod </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> boot(self): </span><span style="color: rgba(0, 0, 255, 1)">pass</span><span style="color: rgba(0, 0, 0, 1)"> @abstractmethod </span><span style="color: rgba(0, 0, 255, 1)">def</span> kill(self, restart=<span style="color: rgba(0, 0, 0, 1)">True): </span><span style="color: rgba(0, 0, 255, 1)">pass</span>
class FileServer(Server):
def init(self):
'''初始化文件服务进程要求的操作'''
self.name = 'FileServer'
self.state = State.new</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> boot(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">booting the {}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">.format(self)) </span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">启动文件服务进程要求的操作</span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(0, 0, 0, 1)"> self.state </span>=<span style="color: rgba(0, 0, 0, 1)"> State.running </span><span style="color: rgba(0, 0, 255, 1)">def</span> kill(self, restart=<span style="color: rgba(0, 0, 0, 1)">True): </span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Killing {}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">.format(self)) </span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">终止文件服务进程要求的操作</span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(0, 0, 0, 1)"> self.state </span>= State.restart <span style="color: rgba(0, 0, 255, 1)">if</span> restart <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> State.zombie </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> create_file(self, user, name, permissions): </span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">检查访问权限的有效性、用户权限等</span><span style="color: rgba(128, 0, 0, 1)">'''</span> <span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">trying to create the file '{}' for user '{}' with permissions{}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">.format(name, user, permissions))
class ProcessServer(Server):
def init(self):
'''初始化进程服务进程要求的操作'''
self.name = 'ProcessServer'
self.state = State.new</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> boot(self): </span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">booting the {}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">.format(self)) </span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">启动进程服务进程要求的操作</span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(0, 0, 0, 1)"> self.state </span>=<span style="color: rgba(0, 0, 0, 1)"> State.running </span><span style="color: rgba(0, 0, 255, 1)">def</span> kill(self, restart=<span style="color: rgba(0, 0, 0, 1)">True): </span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Killing {}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">.format(self)) </span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">终止进程服务进程要求的操作</span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(0, 0, 0, 1)"> self.state </span>= State.restart <span style="color: rgba(0, 0, 255, 1)">if</span> restart <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> State.zombie </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> create_process(self, user, name): </span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">检查用户权限和生成PID等</span><span style="color: rgba(128, 0, 0, 1)">'''</span> <span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">trying to create the process '{}' for user '{}'</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">.format(name, user))
class WindowServer:
passclass NetworkServer:
passclass OperatingSystem:
'''外观'''<span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self): self.fs </span>=<span style="color: rgba(0, 0, 0, 1)"> FileServer() self.ps </span>=<span style="color: rgba(0, 0, 0, 1)"> ProcessServer() </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> start(self): [i.boot() </span><span style="color: rgba(0, 0, 255, 1)">for</span> i <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> (self.fs, self.ps)] </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> create_file(self, user, name, permissions): </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> self.fs.create_file(user, name, permissions) </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> create_process(self, user, name): </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> self.ps.create_process(user, name)
def main():
os = OperatingSystem()
os.start()
os.create_file('foo', 'hello', '-rw-r-r')
os.create_process('bar', 'ls /tmp')if name == 'main':
main()"""
booting the FileServer
booting the ProcessServer
trying to create the file 'hello' for user 'foo' with permissions-rw-r-r
trying to create the process 'ls /tmp' for user 'bar'
"""
享元模式
运用共享技术有效地支持大量细粒度的对象。
内部状态:享元对象中不会随环境改变而改变的共享部分。比如围棋棋子的颜色。
外部状态:随环境改变而改变、不可以共享的状态就是外部状态。比如围棋棋子的位置。
应用场景:程序中使用了大量的对象,如果删除对象的外部状态,可以用相对较少的共享对象取代很多组对象,就可以考虑使用享元模式。
1 import random 2 from enum import Enum 3 TreeType = Enum('TreeType', 'apple_tree cherry_tree peach_tree') 4 5 class Tree: 6 pool = dict() 7 def __new__(cls, tree_type): 8 obj = cls.pool.get(tree_type, None) 9 if not obj: 10 obj = object.__new__(cls) 11 cls.pool[tree_type] = obj 12 obj.tree_type = tree_type 13 return obj 14 15 def render(self, age, x, y): 16 print('render a tree of type {} and age {} at ({}, {})'.format(self.tree_type, age, x, y)) 17 18 19 def main(): 20 rnd = random.Random() 21 age_min, age_max = 1, 30 # 单位为年 22 min_point, max_point = 0, 100 23 tree_counter = 0 24 for _ in range(10): 25 t1 = Tree(TreeType.apple_tree) 26 t1.render(rnd.randint(age_min, age_max), 27 rnd.randint(min_point, max_point), 28 rnd.randint(min_point, max_point)) 29 tree_counter += 1 30 for _ in range(3): 31 t2 = Tree(TreeType.cherry_tree) 32 t2.render(rnd.randint(age_min, age_max), 33 rnd.randint(min_point, max_point), 34 rnd.randint(min_point, max_point)) 35 tree_counter += 1 36 for _ in range(5): 37 t3 = Tree(TreeType.peach_tree) 38 t3.render(rnd.randint(age_min, age_max), 39 rnd.randint(min_point, max_point), 40 rnd.randint(min_point, max_point)) 41 tree_counter += 1 42 43 print('trees rendered: {}'.format(tree_counter)) 44 print('trees actually created: {}'.format(len(Tree.pool))) 45 t4 = Tree(TreeType.cherry_tree) 46 t5 = Tree(TreeType.cherry_tree) 47 t6 = Tree(TreeType.apple_tree) 48 print('{} == {}? {}'.format(id(t4), id(t5), id(t4) == id(t5))) 49 print('{} == {}? {}'.format(id(t5), id(t6), id(t5) == id(t6))) 50 51 main() 52 53 """ 54 render a tree of type TreeType.apple_tree and age 28 at (29, 80) 55 render a tree of type TreeType.apple_tree and age 28 at (38, 94) 56 render a tree of type TreeType.apple_tree and age 16 at (82, 84) 57 render a tree of type TreeType.apple_tree and age 18 at (43, 98) 58 render a tree of type TreeType.apple_tree and age 2 at (84, 72) 59 render a tree of type TreeType.apple_tree and age 16 at (89, 29) 60 render a tree of type TreeType.apple_tree and age 30 at (91, 53) 61 render a tree of type TreeType.apple_tree and age 12 at (92, 73) 62 render a tree of type TreeType.apple_tree and age 3 at (11, 54) 63 render a tree of type TreeType.apple_tree and age 1 at (34, 59) 64 render a tree of type TreeType.cherry_tree and age 11 at (67, 72) 65 render a tree of type TreeType.cherry_tree and age 27 at (65, 81) 66 render a tree of type TreeType.cherry_tree and age 27 at (10, 48) 67 render a tree of type TreeType.peach_tree and age 11 at (35, 38) 68 render a tree of type TreeType.peach_tree and age 3 at (58, 83) 69 render a tree of type TreeType.peach_tree and age 18 at (73, 50) 70 render a tree of type TreeType.peach_tree and age 24 at (94, 3) 71 render a tree of type TreeType.peach_tree and age 4 at (2, 9) 72 trees rendered: 18 73 trees actually created: 3 74 4866032 == 4866032? True 75 4866032 == 4742704? False 76 77 """
模型 - 视图 - 控制器模式
代理模式
3. 行为型模式
责任链模式
命令模式
解释器模式
观察者模式
状态模式
策略模式
模板模式