# 创建型模式
# 抽象工厂模式 (Abstract factory)
提供一个接口, 用于创建相关或依赖对象的家族, 而不需要指定具体类。
"""Implementation of the abstract factory pattern"""
import random
class PetShop:
"""A pet shop"""
def __init__(self, animal_factory=None):
"""pet_factory is our abstract factory.
We can set it at will."""
self.pet_factory = animal_factory
def show_pet(self):
"""Creates and shows a pet using the
abstract factory"""
pet = self.pet_factory.get_pet()
print("This is a lovely", pet)
print("It says", pet.speak())
print("It eats", self.pet_factory.get_food())
# Stuff that our factory makes
class Dog:
def speak(self):
return "woof"
def __str__(self):
return "Dog"
class Cat:
def speak(self):
return "meow"
def __str__(self):
return "Cat"
# Factory classes
class DogFactory:
def get_pet(self):
return Dog()
def get_food(self):
return "dog food"
class CatFactory:
def get_pet(self):
return Cat()
def get_food(self):
return "cat food"
# Create the proper family
def get_factory():
"""Let's be dynamic!"""
return random.choice([DogFactory, CatFactory])()
# Show pets with various factories
if __name__ == "__main__":
shop = PetShop()
for i in range(3):
# 通过get_factory函数来获取不同的工厂类
shop.pet_factory = get_factory()
shop.show_pet()
print("=" * 20)
# 单例模式 (Singleton pattern)
确保一个类只有一个实例, 并提供全局访问点。
class S:
instance = None
def __new__(cls, *args, **kwargs):
if S.instance is None:
S.instance = super().__new__(cls)
def __init__(self):
pass
s1 = S()
print(id(s1))
s2 = S()
print(id(s2))
# 工厂模式(factory method pattern)
定义了一个创建对象的接口, 但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
class GreekGetter:
"""A simple localizer a la gettext"""
def __init__(self):
self.trans = dict(dog="σκύλος", cat="γάτα")
def get(self, msgid):
"""We'll punt if we don't have a translation"""
try:
return self.trans[msgid]
except KeyError:
return str(msgid)
class EnglishGetter:
"""Simply echoes the msg ids"""
def get(self, msgid):
return str(msgid)
def get_localizer(language="English"):
"""The factory method"""
# 根据传入的language来决定要实例的是哪一个类
languages = dict(English=EnglishGetter, Greek=GreekGetter)
return languages[language]()
# Create our localizers
e, g = get_localizer("English"), get_localizer("Greek")
# Localize some text
for msgid in "dog parrot cat bear".split():
print(e.get(msgid), g.get(msgid))
另一个简单的例子
class Person:
def __init__(self):
self.name = None
self.gender = None
def getName(self):
return self.name
def getGender(self):
return self.gender
class Male(Person):
def __init__(self, name):
print "Hello Mr." + name
class Female(Person):
def __init__(self, name):
print "Hello Miss." + name
class 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")
# 生成器模式(Builder pattern)
使用生成器模式封装一个产品的构造过程, 并允许按步骤构造。将一个复杂对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示。
from abc import ABCMeta, abstractmethod
class Builder():
__metaclass__ = ABCMeta
@abstractmethod
def draw_left_arm(self):
pass
@abstractmethod
def draw_right_arm(self):
pass
@abstractmethod
def draw_left_foot(self):
pass
@abstractmethod
def draw_right_foot(self):
pass
@abstractmethod
def draw_head(self):
pass
@abstractmethod
def draw_body(self):
pass
class Thin(Builder):
def draw_left_arm(self):
print '画左手'
def draw_right_arm(self):
print '画右手'
def draw_left_foot(self):
print '画左脚'
def draw_right_foot(self):
print '画右脚'
def draw_head(self):
print '画头'
def draw_body(self):
print '画瘦身体'
class Fat(Builder):
def draw_left_arm(self):
print '画左手'
def draw_right_arm(self):
print '画右手'
def draw_left_foot(self):
print '画左脚'
def draw_right_foot(self):
print '画右脚'
def draw_head(self):
print '画头'
def draw_body(self):
print '画胖身体'
class Director():
def __init__(self, person):
self.person=person
def 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()
# 原型模式(prototype pattern)
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式本质就是克隆对象,所以在对象初始化操作比较复杂的情况下,很实用,能大大降低耗时,提高性能,因为“不用重新初始化对象,而是动态地获得对象运行时的状态”。
import copy
from collections import OrderedDict
class Book:
def __init__(self, name, authors, price, **rest):
'''rest的例子有:出版商、长度、标签、出版日期'''
self.name = name
self.authors = authors
self.price = price # 单位为美元
self.__dict__.update(rest)
def __str__(self):
mylist = []
ordered = OrderedDict(sorted(self.__dict__.items()))
for i in ordered.keys():
mylist.append('{}: {}'.format(i, ordered[i]))
if i == 'price':
mylist.append('$')
mylist.append('\n')
return ''.join(mylist)
class Prototype:
def __init__(self):
self.objects = dict()
def register(self, identifier, obj):
self.objects[identifier] = obj
def unregister(self, identifier):
del self.objects[identifier]
def clone(self, identifier, **attr):
found = self.objects.get(identifier)
if not found:
raise ValueError('Incorrect object identifier: {}'.format(identifier))
obj = copy.deepcopy(found)
obj.__dict__.update(attr)
return 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
"""
简单例子
import copy
class Prototype:
def __init__(self):
self._objects = {}
def register_object(self, name, obj):
"""Register an object"""
self._objects[name] = obj
def unregister_object(self, name):
"""Unregister an object"""
del self._objects[name]
def clone(self, name, **attr):
"""Clone a registered object and update inner attributes dictionary"""
obj = copy.deepcopy(self._objects.get(name))
obj.__dict__.update(attr)
return obj
def main():
class A:
pass
a = A()
prototype = Prototype()
prototype.register_object('a', a)
b = prototype.clone('a', a=1, b=2, c=3)
print(a)
print(b.a, b.b, b.c)
if __name__ == '__main__':
main()