Last active
November 28, 2019 03:38
-
-
Save stoensin/863feff986b414c3d43949380182ca38 to your computer and use it in GitHub Desktop.
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行 主要解决:主要解决接口选择的问题 何时使用:我们明确地计划不同条件下创建不同实例时 如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品 关键代码:创建过程在其子类执行 使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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)) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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