Skip to content

Instantly share code, notes, and snippets.

@stoensin
Last active November 28, 2019 03:38
Show Gist options
  • Save stoensin/863feff986b414c3d43949380182ca38 to your computer and use it in GitHub Desktop.
Save stoensin/863feff986b414c3d43949380182ca38 to your computer and use it in GitHub Desktop.
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行 主要解决:主要解决接口选择的问题 何时使用:我们明确地计划不同条件下创建不同实例时 如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品 关键代码:创建过程在其子类执行 使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
#!/usr/bin/python
#coding:utf8
'''
Abstract Factory
抽象工厂模式也就是不仅生产鼠标,同时生产键盘。
也就是 PC 厂商是个父类,有生产鼠标,生产键盘两个接口。
戴尔工厂,惠普工厂继承它,可以分别生产戴尔鼠标+戴尔键盘,和惠普鼠标+惠普键盘。
创建工厂时,由戴尔工厂创建。
后续工厂.生产鼠标()则生产戴尔鼠标,工厂.生产键盘()则生产戴尔键盘。
'''
#simple
class A:
def __init__(self):
self.word = "运行A"
def run(self):
print(self.word)
class B:
def __init__(self):
self.word = "运行B"
def run(self):
print(self.word)
class AbcInterface:
"""
抽象工厂模式接口类:不需要具体指明实例化A类或B类,对class抽象,对变更友好,符合开闭原则
:param classname:
:return:
"""
def __init__(self, classname=None):
self.test = classname
def run(self):
self.test().run()
if __name__ == '__main__':
test1 = Interface()
test1.test = A
test1.run()
test1.test = B
test1.run()
#one
class Frog:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
def interact_with(self, obstacle):
""" 不同类型玩家遇到的障碍不同 """
print('{} the Frog encounters {} and {}!'.format(
self, obstacle, obstacle.action()))
class Bug:
def __str__(self):
return 'a bug'
def action(self):
return 'eats it'
class FrogWorld:
def __init__(self, name):
print(self)
self.player_name = name
def __str__(self):
return '\n\n\t----Frog World -----'
def make_character(self):
return Frog(self.player_name)
def make_obstacle(self):
return Bug()
class Wizard:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
def interact_with(self, obstacle):
print('{} the Wizard battles against {} and {}!'.format(
self, obstacle, obstacle.action()))
class Ork:
def __str__(self):
return 'an evil ork'
def action(self):
return 'kill it'
class WizardWorld:
def __init__(self, name):
print(self)
self.player_name = name
def __str__(self):
return '\n\n\t------ Wizard World -------'
def make_character(self):
return Wizard(self.player_name)
def make_obstacle(self):
return Ork()
class GameEnvironment:
""" 抽象工厂,根据不同的玩家类型创建不同的角色和障碍 (游戏环境)
这里可以根据年龄判断,成年人返回『巫师』游戏,小孩返回『青蛙过河』游戏"""
def __init__(self, factory):
self.hero = factory.make_character()
self.obstacle = factory.make_obstacle()
def play(self):
self.hero.interact_with(self.obstacle)
def validate_age(name):
try:
age = input('Welcome {}. How old are you?'.format(name))
age = int(age)
except ValueError as err:
print("Age {} is valid, plz try again...".format(age))
return (False, age)
return (True, age)
def main():
name = input("Hello. What's your name?")
valid_input = False
while not valid_input:
valid_input, age = validate_age(name)
game = FrogWorld if age < 18 else WizardWorld
enviroment = GameEnviroment(game(name))
enviroment.play()
#!/usr/bin/python
#coding:utf8
#simple 使得构建与它的表示分离,使得同样的构建过程可以创建不同的表示
#建造者模式应该有几个关键要素:相同的流程、不同的表示、修建者。
#也就是同一个对象(建筑)在同一修建者组织下,以相同的实例化流程(施工流程)来达到不同的表示效果(毛坯、写字楼)
class Builder():
"""建造流程:原料->施工"""
def __init__(self):
self.materiel = None
self.design = None
def run(self):
print('修建完工!设计建筑: %s | 购买原料: %s' % (self.design, self.materiel))
class A(Builder):
"""方案A,修建毛坯房"""
def get_materiel(self):
self.materiel = "砖瓦"
def get_design(self):
self.design = "毛坯房"
class B(Builder):
"""方案B,修建写字楼"""
def get_materiel(self):
self.materiel = "玻璃"
def get_design(self):
self.design = "写字楼"
class Director:
"""调度:买原料-组织施工"""
def __init__(self):
self.programme = None
def build(self):
self.programme.get_materiel()
print("购买原料:{}".format(self.programme.materiel))
self.programme.get_design()
print("设计方案:{}".format(self.programme.design))
self.programme.run()
if __name__ == '__main__':
# 修建毛坯房
test = Director()
test.programme = A()
test.build()
# 修建写字楼
test = Director()
test.programme = B()
test.build()
'''
购买原料:砖瓦
设计方案:毛坯房
修建完工!设计建筑: 毛坯房 | 购买原料: 砖瓦
购买原料:玻璃
设计方案:写字楼
修建完工!设计建筑: 写字楼 | 购买原料: 玻璃
'''
class Computer:
def __init__(self, serial_number):
self.serial = serial_number
self.memory = None # in gigabytes
self.hdd = None # in gigabytes
self.gpu = None
def __str__(self):
info = ('Memory: {}GB'.format(self.memory),
'Hard Disk: {}GB'.format(self.hdd),
'Graphics Card: {}'.format(self.gpu))
return '\n'.join(info)
class ComputerBuilder:
def __init__(self):
self.computer = Computer('AG23385193')
def configure_memory(self, amount):
self.computer.memory = amount
def configure_hdd(self, amount):
self.computer.hdd = amount
def configure_gpu(self, gpu_model):
self.computer.gpu = gpu_model
class HardwareEngineer:
def __init__(self):
self.builder = None
def construct_computer(self, memory, hdd, gpu):
self.builder = ComputerBuilder()
[step for step in (self.builder.configure_memory(memory),
self.builder.configure_hdd(hdd),
self.builder.configure_gpu(gpu))]
@property
def computer(self):
return self.builder.computer
engineer = HardwareEngineer()
engineer.construct_computer(hdd=500, memory=8, gpu='GeForce GTX 650 Ti')
computer = engineer.computer
print(computer)
#!/usr/bin/python
#coding:utf8
'''
Factory Method
工厂模式也就是鼠标工厂是个父类,有生产鼠标这个接口。
戴尔鼠标工厂,惠普鼠标工厂继承它,可以分别生产戴尔鼠标,惠普鼠标。
生产哪种鼠标不再由参数决定,而是创建鼠标工厂时,由戴尔鼠标工厂创建。
后续直接调用鼠标工厂.生产鼠标()即可
'''
#simple
class A:
def __init__(self):
self.word = "运行A"
def run(self):
print(self.word)
class B:
def __init__(self):
self.word = "运行B"
def run(self):
print(self.word)
def FactoryInterface(classname):
"""
工厂模式接口函数:若有变更时,不满足开闭原则,所以可以升级到抽象工厂
:param classname:
:return:
"""
run = dict(A=A, B=B)
return run[classname]()
if __name__ == '__main__':
test1 = Interface('A')
test1.run()
test2 = Interface('B')
test2.run()
#two
import json
import xml.etree.ElementTree as etree
class JSONConnector:
def __init__(self, filepath):
self.data = dict()
with open(filepath, mode='r', encoding='utf8') as f:
self.data = json.load(f)
@property
def parsed_data(self):
return self.data
class XMLConnector:
def __init__(self, filepath):
self.tree = etree.parse(filepath)
@property
def parsed_data(self):
return self.tree
def connection_factory(filepath):
""" 工厂方法 """
if filepath.endswith('json'):
connector = JSONConnector
elif filepath.endswith('xml'):
connector = XMLConnector
else:
raise ValueError('Cannot connect to {}'.format(filepath))
return connector(filepath)
#three
MINI14 = '1.4GHz Mac mini'
class AppleFactory:
class MacMini14:
def __init__(self):
self.memory = 4 # in gigabytes
self.hdd = 500 # in gigabytes
self.gpu = 'Intel HD Graphics 5000'
def __str__(self):
info = ('Model: {}'.format(MINI14),
'Memory: {}GB'.format(self.memory),
'Hard Disk: {}GB'.format(self.hdd),
'Graphics Card: {}'.format(self.gpu))
return '\n'.join(info)
def build_computer(self, model):
if model == MINI14:
return self.MacMini14()
else:
print("I don't know how to build {}".format(model))
# 使用工厂
afac = AppleFactory()
mac_mini = afac.build_computer(MINI14)
print(mac_mini)
#one
class ChinaGetter:
"""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"""
languages = dict(English=EnglishGetter, China=ChinaGetter)
return languages[language]()
e, g = get_localizer("English"), get_localizer("China")
for msgid in "dog parrot cat bear".split():
print(e.get(msgid), g.get(msgid))
#!/usr/bin/python
#coding:utf8
'''
Prototype 原型模式最为核心的两点是:拷贝、属性更新
'''
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:
def __str__(self):
return "I am A"
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)
class Information:
"""个人信息"""
def __init__(self):
self.name = None
self.ager = None
self.height = None
def run(self):
"""
自我介绍方法
:return:
"""
print("我叫{}: 年龄:{} 身高:{}".format(self.name, self.ager, self.height))
class Prototype:
def __init__(self, obj):
self.copy_object = obj()
def clone(self, **attr):
obj = copy.deepcopy(self.copy_object)
obj.__dict__.update(attr)
return obj
if __name__ == '__main__':
test = Prototype(Information)
a = test.clone(name='张山', ager="30", height='170cm')
a.run()
b = test.clone(name='李飞', ager="20", height='190cm')
b.run()
#!/usr/bin/python
#coding:utf8
'''
Singleton
'''
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
org = super(Singleton, cls)
cls._instance = org.__new__(cls, *args, **kw)
return cls._instance
class SingleSpam(Singleton):
def __init__(self, s):
self.s = s
def __str__(self):
return self.s
s1 = SingleSpam('spam')
print(id(s1), s1)
def singleton(cls):
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class Foo(object):
pass
foo1 = Foo()
foo2 = Foo()
print (foo1 is foo2) #True
class Singleton(type):
def __call__(cls,*args,**kwargs):
if not hasattr(cls,'_instance'):
cls._instance = super(Singleton,cls).__call__(*args,**kwargs)
return cls._instance
class Foo(object):
__metaclass__ = Singleton
foo1 = Foo()
foo2 = Foo()
print (foo1 is foo2) #True
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment