@nemos
        
        2017-05-06T02:43:57.000000Z
        字数 14768
        阅读 860
    cs关于示例代码 由于示例代码大概是从三四个不同的地方收集而来还有部分是我自己写的,所以代码风格不一,敬请谅解。 
大部分被收集来的我强行魔改了,删掉了不影响理解的空白和注释尽,可能保持短小和易于理解。
有需求可以看详细代码,当然详细代码和我贴的示例代码不一样是很正常的事情。 
ps.如果我有改错代码,欢迎提醒。
上面的所有原则用一句话来概括就是:高内聚低耦合
出自《设计模式解析》 
这里只列举了一下,因为内容是一些逻辑性的推导过程,所以详细请参考上书。
模式的层次与不同的组合。
对功能和实现作聚类处理然后拼接。
用于描述类建模的图
 
矩形表示一个类,包含1.类名 2.类的数据成员 3.类的方法 
访问权限::+公开的 -私有的 #受保护的 

表示动态关系 

对类的各种创建行为进行控制的模式。
说明 
建立一个工厂函数,对实现了同一接口的一些类进行实例的创建。 
 
示例代码 
详细代码 
PS.原来的代码感觉并不好理解,被我改了
class MailSender(object):def send(self, msg):print('mail message {msg} sended'.format(msg=msg))class SmsSender(object):def send(self, msg):print('sms message {msg} sended'.format(msg=msg))def get_sender(sender="mail"): #The factory methodsenders = dict(mail=MailSender, sms=SmsSender)return senders[language]()m, s = get_senderr(sender="mail"), get_sender(sender="sms")for msg in "A B".split():print(m.send(msg), '\n', s.send(msg))### OUTPUT #### mail message A sended# sms message A sended# mail message B sended# sms message B sended
说明 
工厂模式中类的创建依赖的工厂方法,一旦想添加一个新类就要修改工厂方法。 
在抽象工厂模式中则由工厂提供统一的接口来创建类。 
添加一个新类并不需要修改工厂方法。 
 
示例代码 
详细代码
class PetShop(object):def __init__(self, animal_factory=None):self.pet_factory = animal_factorydef show_pet(self):pet = self.pet_factory.get_pet()print(pet.speak)# Concrete classesclass Dog(object):def speak(self):return "woof"class Cat(object):def speak(self):return "meow"# Factory classesclass DogFactory(object):def get_pet(self):return Dog()class CatFactory(object):def get_pet(self):return Cat()# Create the proper familydef get_factory():return random.choice([DogFactory, CatFactory])()# Show pets with various factoriesshop = PetShop(get_factory())shop.show_pet()### OUTPUT #### woof
说明 
工厂模式只创建了单个对象,创建者模式用于创建复合对象。 
 
示例代码 
详细代码
class Director(object):def __init__(self):self.builder = Nonedef construct_building(self):self.builder.new_building()self.builder.build_size()def get_building(self):return self.builder.building# Abstract Builderclass Builder(object):def __init__(self):self.building = Nonedef new_building(self):self.building = Building()def build_size(self):raise NotImplementedError# Concrete Builderclass BuilderHouse(Builder):def build_size(self):self.building.size = 'Big'# Productclass Building(object):def __init__(self):self.size = Nonedef __repr__(self):return 'Size: {0.size}'.format(self)# Clientdirector = Director()director.builder = BuilderHouse()director.construct_building()building = director.get_building()print(building)### OUTPUT #### Size: Big
说明 
简化复杂而差异较小的对象的创建过程。 
 
示例代码 
详细代码
import copyclass Book(object):def __init__(self, **info):self.__dict__.update(info)class Prototype(object):def __init__(self):self._objects = dict()def clone(self, identifier, **attrs):obj = copy.deepcopy(self._objects[identifier])obj.__dict__.update(attrs)return objdef register(self, identifier, obj):self._objects[identifier] = obj### TEST ###prototype = Prototype()book_first_edition = Book(name='python', author='somebody', edition='first')prototype.register('a python book', book_first_edition)book_second_edition = prototype.clone('a python book', edition='second')print([{key: value} for key, value in book_first_edition.__dict__.items()])print([{key: value} for key, value in book_second_edition.__dict__.items()])### OUTPUT #### [{'name': 'python'}, {'edition': 'first'}, {'author': 'somebody'}]# [{'name': 'python'}, {'edition': 'second'}, {'author': 'somebody'}]
说明 
一个只允许实例化一次的类,提供全局的使用接口。 
并不建议使用该模式 
代码
class Singleton(object):cer = Truedef __new__(cls):if cls.cer:cls.cer = Falsereturn super().__new__(cls)else:raisedef __del__(self):self.__class__.cer = True
结构行为是在原有对象的情况下对其进行应用。
说明 
将拥有不同接口的对象统一成相同接口的对象。 
或者为为接口作适配。 
 
示例代码 
详细代码
class Dog(object):def bark(self):return "woof!"class Human(object):def speak(self):return "'hello'"class Car(object):def make_noise(self, octane_level):return "vroom{0}".format("!" * octane_level)class Adapter(object):def __init__(self, obj, **adapted_methods):self.obj = objself.__dict__.update(adapted_methods)def __getattr__(self, attr):return getattr(self.obj, attr)### TEST ###objects = []objects.append(Adapter(Dog(), make_noise=dog.bark))objects.append(Adapter(Human(), make_noise=human.speak))objects.append(Adapter(Car(), make_noise=lambda: car.make_noise(3)))for obj in objects:print("A {0} goes {1}".format(obj.name, obj.make_noise()))### OUTPUT #### A Dog goes woof!# A Human goes 'hello'# A Car goes vroom!!!
说明 
即为多个过程给予一个统一的接口。 
 
示例代码 
详细代码(这里并没有用到)
class CPU(object):def startup(self):print('CPU startup.')def shutdown(self);print('CPU shutdown')class Memory(object):def startup(self):print('Memory startup.')def shutdown(self);print('Memory shutdown')class Computrt(object):def __init__(self):self.cpu = CPU()self.memory = Memory()def startup(self):self.cpu.startup()self.memory.startup()def shutdown(self);self.cpu.shutdown()self.memory.shutdown()### TEST ###computer = Computer()computer.startup()computer.shutdown()### OUTPUT #### CPU startup.# Memory startup.# CPU shutdown# Memory shutdown
说明 
可以给对象动态的增加一些功能,装饰对象与原对象接口不变且装饰对象持有原对象的实例。 
python内置的@关键字实现了本模式,以下代码仅作通用性的示范。 
 
示例代码 
详细代码
class TextTag(object):def __init__(self, text):self._text = textdef render(self):return self._textclass BoldWrapper(object):def __init__(self, wrapped):self._wrapped = wrappeddef render(self):return "<b>{}</b>".format(self._wrapped.render())### TEST ###simple_hello = TextTag("hello, world!")special_hello = BoldWrapper(simple_hello)print("before:", simple_hello.render())print("after:", special_hello.render())### OUTPUT #### before: hello, world!# after: <b>hello, world!</b>
说明 
对原有方法行为进行控制,而不修改方法本身。 
注意本模式跟装饰器模式区别,装饰器是动态的,而代理是静态的。 
装饰器一般会包裹整个类而保留相同接口。 
而代理可以部分包裹类。 
 
示例代码 
详细代码
class SalesManager(object):def talk(self):print("Sales Manager ready to talk")class Proxy(object):def __init__(self):self.busy = 'No'self.sales = Nonedef talk(self):print("Proxy checking for Sales Manager availability")if self.busy == 'No':self.sales = SalesManager()self.sales.talk()else:print("Sales Manager is busy")### TEST ###p = Proxy()p.talk()p.busy = 'Yes'p.talk()### OUTPUT #### Proxy checking for Sales Manager availability# Sales Manager ready to talk# Proxy checking for Sales Manager availability# Sales Manager is busy
说明 
处理树状结构的对象关联,如gui中各种窗口组件。 
 
示例代码 
详细代码 
原代码太长了,这里做了大量简化处理。
class Node(object):next_node = []def __init__(self, name):self.name = namedef add_node(self, node):self.append(node)### TEST ###window = Node('window')frame1 = Node('frame1')frame2 = Node('frame2')window.add_node(frame1)window.add_node(frame2)
说明 
利用对象池实现了对象之间的共享,在大量创建对象的情况下可以节约内存。
示例代码 
详细代码 
一片森林有多颗树,但是树种类相同。
class Tree:pool = dict()def __new__(cls, tree_type):obj = cls.pool.get(tree_type, None)if not obj:obj = object.__new__(cls)cls.pool[tree_type] = objobj.tree_type = tree_typereturn objdef show(self, x, y):print('a {type} tree in ({x}, {y})'.format(type=self.tree_type, x=x, y=y))### TEST ###tree = Tree('apple_tree')[tree.show(randint(0, 100), randint(0, 100)) for _ in range(10)]### OUTPUT #### a apple_tree tree in (32, 57)# a apple_tree tree in (39, 57)# a apple_tree tree in (86, 38)
说明 
将抽象与实现解耦,使得二者可以独立变化 
 
示例代码 
详细代码
class DrawingAPI1(object):def draw(self):print('API1 Drawing')class DrawingAPI2(object):def draw(self):print('API2 Drawing')class Shape(object):def __init__(self,drawing_api):self._drawing_api = drawing_apidef draw(self):self._drawing_api.draw()### TEST ###shapes = (CircleShape(DrawingAPI1()),CircleShape(DrawingAPI2()))for shape in shapes:shape.draw()### OUTPUT #### API1 Drawing# API2 Drawing
行为模式涉及了对象与算法间的分配关系。
说明 
将算法的选择与实现分离。 
 
示例代码 
详细代码
import typesclass Strategy(object):def __init__(self, calculator=None):self.name = 'Strategy 0'if func is not None:self.execute = types.MethodType(calculator, self) #绑定方法def execute(self):print(self.name)def do_calculator1(self):print(self.name, 'do calculator1')def do_calculator2(self):print(self.name, 'do calculator2')### TEST ###strat = Strategy(do_calculator1)strat.execute()### OUTPUT #### Strategy 0 do calculator1
说明 
消除冗余,对算法的部分进行定制处理。 
 
示例代码 
详细代码
ingredients = "spam eggs apple"line = '-' * 10# Skeletonsdef iter_elements(getter, action):for element in getter():action(element)print(line)def rev_elements(getter, action):for element in getter()[::-1]:action(element)print(line)# Gettersdef get_list():return ingredients.split()def get_lists():return [list(x) for x in ingredients.split()]# Actionsdef print_item(item):print(item)def reverse_item(item):print(item[::-1])# Makes templatesdef make_template(skeleton, getter, action):def template():skeleton(getter, action)return template# Create our template functionstemplates = [make_template(s, g, a)for g in (get_list, get_lists)for a in (print_item, reverse_item)for s in (iter_elements, rev_elements)]# Execute themfor template in templates:template()### OUTPUT #### spam# ----------# eggs# ----------# apple# ----------# apple# ----------# eggs# ----------# spam# ----------# maps# ----------# sgge# ----------# elppa# ----------# elppa# ----------# sgge# ----------# maps# ----------# ['s', 'p', 'a', 'm']# ----------# ['e', 'g', 'g', 's']# ----------# ['a', 'p', 'p', 'l', 'e']# ----------# ['a', 'p', 'p', 'l', 'e']# ----------# ['e', 'g', 'g', 's']# ----------# ['s', 'p', 'a', 'm']# ----------# ['m', 'a', 'p', 's']# ----------# ['s', 'g', 'g', 'e']# ----------# ['e', 'l', 'p', 'p', 'a']# ----------# ['e', 'l', 'p', 'p', 'a']# ----------# ['s', 'g', 'g', 'e']# ----------# ['m', 'a', 'p', 's']# ----------
说明 
用于消息传递的模型,每一个节点持有下一个的应用然后将一个事件沿着链一直传递下去,直到事件被处理。 
 
示例代码 
其他参考代码 
详细代码
class Event(object):def __init__(self, name):self.name = namedef __str__(self):return self.nameclass Widget(object):def __init__(self, parent=None):self.parent = parentdef handler(self, event):if not self._handle(event):self.parent.handler(event)def _handle(self, event):raise NotImplementedErrorclass MainWindow(Widget):def _handle(self, event):if 'a' in str(event):print('MainWindow handled event {}'.format(event))return Trueelse:print('in MainWindow event {} passed py'.format(event))return Falseclass SendDialog(Widget):def _handle(self, event):if 'b' in str(event):print('SendDialog handled event {}'.format(event))return Trueelse:print('in SendDialog event {} passed py'.format(event))return Falseclass MsgText(Widget):def _handle(self, event):if 'c' in str(event):print('MsgText handled event {}'.format(event))return Trueelse:print('in MsgText event {} passed py'.format(event))return Falseclass Out(Widget):def _handle(self, event):print('event {} has no hander'.format(event))return True### TEST ###mw = MainWindow(Out())sd = SendDialog(mw)msg = MsgText(sd)for e in 'bd':evt = Event(e)msg.handler(evt)### OUTPUT #### in MsgText event b passed py# SendDialog handled event b# in MsgText event d passed py# in SendDialog event d passed py# in MainWindow event d passed py# event d has no hander
说明 
比较容易理解的是文本编辑器中撤销操作的实现,即将操作封装成一个对象。然后维护一个命令的队列。 
 
示例代码 
详细代码
import osfrom os.path import lexistsclass MoveFileCommand(object):def __init__(self, src, dest):self.src = srcself.dest = destdef execute(self):self.rename(self.src, self.dest)def undo(self):self.rename(self.dest, self.src)def rename(self, src, dest):print('renaming {} to {}'.format(src, dest))os.rename(src, dest)### TEST ###command_stack = []command_stack.append(MoveFileCommand('foo.txt', 'bar.txt'))command_stack.append(MoveFileCommand('bar.txt', 'baz.txt'))for cmd in command_stack:cmd.execute()for cmd in reversed(command_stack):cmd.undo()### OUTPUT #### renaming foo.txt to bar.txt# renaming bar.txt to baz.txt# renaming baz.txt to bar.txt# renaming bar.txt to foo.txt
说明 
其实叫备份模式比较好理解。 
即对对象的状态进行备份和存储以使对象在需要的时刻可以恢复到之前的状态。 
如实现一个回滚的操作。 
 
示例代码 
详细代码 
这里用到了一点动态语言闭包的小技巧。
from copy import deepcopyclass Memento(object):def __init__(self, obj):state = deepcopy(obj.__dict__)def rollback():obj.__dict__.clear()obj.__dict__.update(state)self.rollback = rollbackclass Forgettable(object):def __init__(self, value):self.value = valuedef __str__(self):return self.valuedef commit(self):self.memo = Memento(self)def rollback(self):self.memo.rollback()### TEST ###forget_it = Forgettable('something you cant forget')forget_it.commit()print(forget_it)forget_it.value = 'I forgot it'print(forget_it)forget_it.rollback()print(forget_it)### OUTPUT #### something you cant forget# I forgot it# something you cant forget
说明 
当对象的状态改变时同时改变其行为。 
 
示例代码 
详细代码
class State(object):def scan(self):self.pos += 1print("Scanning... Station is", self.stations[self.pos], self.name)class AmState(State):def __init__(self, radio):self.radio = radioself.stations = ["1250", "1380", "1510"]self.pos = 0self.name = "AM"def toggle_amfm(self):print("Switching to FM")self.radio.state = self.radio.fmstateclass FmState(State):def __init__(self, radio):self.radio = radioself.stations = ["81.3", "89.1", "103.9"]self.pos = 0self.name = "FM"def toggle_amfm(self):print("Switching to AM")self.radio.state = self.radio.amstateclass Radio(object):def __init__(self):self.amstate = AmState(self)self.fmstate = FmState(self)self.state = self.amstatedef toggle_amfm(self):self.state.toggle_amfm()def scan(self):self.state.scan()### TEST ###radio = Radio()radio.scan()radio.toggle_amfm()radio.scan()### OUTPUT #### Scanning... Station is 1380 AM# Switching to FM# Scanning... Station is 89.1 FM
说明 
将数据结构及其操作解耦,用于数据结构稳定但其算法多变的系统。 

示例代码 
详细代码
这个例子并不是特别好理解。类的mro是固定的结构,使用visit方法对树进行遍历,如果visitor中有处理相应节点的方法则调用。
class Node(object):passclass A(Node):passclass B(Node):passclass C(A, B):passclass Visitor(object):def visit(self, node, *args, **kwargs):meth = Nonefor cls in node.__class__.__mro__:meth_name = 'visit_' + cls.__name__meth = getattr(self, meth_name, None)if meth:breakif not meth:meth = self.generic_visitreturn meth(node, *args, **kwargs)def generic_visit(self, node, *args, **kwargs):print('generic_visit ' + node.__class__.__name__)def visit_B(self, node, *args, **kwargs):print('visit_B ' + node.__class__.__name__)### TEST ###a = A()b = B()c = C()visitor = Visitor()visitor.visit(a)visitor.visit(b)visitor.visit(c)### OUTPUT #### generic_visit A# visit_B B# visit_B C
说明 
解决类与类之间的依赖关系中间加一层mediator来解耦。 
即类与类之间存在依赖关系时通过来mediator来共享关系。 
 
示例代码 
详细代码
class Worker(object):def __init__(self, mediator):self.mediator = mediatorclass Worker1(Work):def work()def work_with_work2():self.mediator.work2class Worker2(Work):def work():def work_with_work1():self.mediator.work1class Mediator(object):def __init__(self):self.worker1 = Worker1(self)self.worker2 = Worker2(self)def work();self.worker1.work()self.worker2.work()
说明 
当对象变化时其依赖的对象都会收到通知并随之变化 
 
示例代码 
详细代码
class Subject(object):def __init__(self):self._observers = []def attach(self, observer):self._observers.append(observer)def detach(self, observer):self._observers.remove(observer)def notify(self):for observer in self._observers:observer.update(self)class MySubject(Subject):def __init__(self, name=''):super().__init__(self)self.name = namedef subject_changed(self):self.notify()class Viewer1:def update(self, subject):print('Viewer1: Subject %s changed' % (subject.name,))class Viewer2:def update(self, subject):print('Viewer2: Subject %s changed' % (subject.name,))### TEST ###subject1 = MySubject('MySubject')view1 = Viewer1()view2 = Viewer2()subject1.attach(view1)subject1.attach(view2)subject1.subject_changed()### OUTPUT #### Viewer1: Viewer2: Subject Mysubject changed# Viewer2: Viewer2: Subject Mysubject changed
design-patterns-for-humans 
《设计模式解析》 
cnblog设计模式 
python示例代码来源 
精通Python设计模式(这书挺烂的,并不建议看,拿了一部分源码参考)