[关闭]
@nemos 2017-05-06T02:43:57.000000Z 字数 14768 阅读 806

设计模式

cs

本文使用说明

关于示例代码 由于示例代码大概是从三四个不同的地方收集而来还有部分是我自己写的,所以代码风格不一,敬请谅解。
大部分被收集来的我强行魔改了,删掉了不影响理解的空白和注释尽,可能保持短小和易于理解。

有需求可以看详细代码,当然详细代码和我贴的示例代码不一样是很正常的事情。
ps.如果我有改错代码,欢迎提醒。

六大原则

1.开闭原则(Open Close Principle)
开闭原则即对拓展开放,对修改关闭。也就是说在原有的代码上进行拓展,而不是去修改原来的代码。
2.里氏代换原则(Liskov Substitution Principle)
即父类一定可以使用子类所有实现,即父类是对子类拓展而不能修改子类。
3.依赖倒转原则(Dependence Inversion Principle)
即所谓的自顶向下的设计原则。
4.接口隔离原则(Interface Segregation Principle)
使用多个隔离的接口代替单接口来降低耦合度。
5.迪米特法则(最少知道原则)(Demeter Principl)
实体之间尽量少发生关系,使功能模块相对独立。
6.合成复用原则(Composite Reuse Principle)
尽量使用类之间的组合来代替继承关系

上面的所有原则用一句话来概括就是:高内聚低耦合


如何用模式思考

出自《设计模式解析》
这里只列举了一下,因为内容是一些逻辑性的推导过程,所以详细请参考上书。

模式组合

模式的层次与不同的组合。

(CVA)共性与可变性分析

对功能和实现作聚类处理然后拼接。

分析矩阵


UML

用于描述类建模的图

类图

类图
矩形表示一个类,包含1.类名 2.类的数据成员 3.类的方法
访问权限::+公开的 -私有的 #受保护的
表示关系的UML

交互图

表示动态关系
交互图


Crational(创建行为)

对类的各种创建行为进行控制的模式。

Factory Method(工厂方法)

说明
建立一个工厂函数,对实现了同一接口的一些类进行实例的创建。
Factory Method.png
示例代码
详细代码
PS.原来的代码感觉并不好理解,被我改了

  1. class MailSender(object):
  2. def send(self, msg):
  3. print('mail message {msg} sended'.format(msg=msg))
  4. class SmsSender(object):
  5. def send(self, msg):
  6. print('sms message {msg} sended'.format(msg=msg))
  7. def get_sender(sender="mail"): #The factory method
  8. senders = dict(mail=MailSender, sms=SmsSender)
  9. return senders[language]()
  10. m, s = get_senderr(sender="mail"), get_sender(sender="sms")
  11. for msg in "A B".split():
  12. print(m.send(msg), '\n', s.send(msg))
  13. ### OUTPUT ###
  14. # mail message A sended
  15. # sms message A sended
  16. # mail message B sended
  17. # sms message B sended

Abstract Factory(抽象工厂)

说明
工厂模式中类的创建依赖的工厂方法,一旦想添加一个新类就要修改工厂方法。
在抽象工厂模式中则由工厂提供统一的接口来创建类。
添加一个新类并不需要修改工厂方法。
Abstract Factory
示例代码
详细代码

  1. class PetShop(object):
  2. def __init__(self, animal_factory=None):
  3. self.pet_factory = animal_factory
  4. def show_pet(self):
  5. pet = self.pet_factory.get_pet()
  6. print(pet.speak)
  7. # Concrete classes
  8. class Dog(object):
  9. def speak(self):
  10. return "woof"
  11. class Cat(object):
  12. def speak(self):
  13. return "meow"
  14. # Factory classes
  15. class DogFactory(object):
  16. def get_pet(self):
  17. return Dog()
  18. class CatFactory(object):
  19. def get_pet(self):
  20. return Cat()
  21. # Create the proper family
  22. def get_factory():
  23. return random.choice([DogFactory, CatFactory])()
  24. # Show pets with various factories
  25. shop = PetShop(get_factory())
  26. shop.show_pet()
  27. ### OUTPUT ###
  28. # woof

Builder(建造者)

说明
工厂模式只创建了单个对象,创建者模式用于创建复合对象。
Builder pattern
示例代码
详细代码

  1. class Director(object):
  2. def __init__(self):
  3. self.builder = None
  4. def construct_building(self):
  5. self.builder.new_building()
  6. self.builder.build_size()
  7. def get_building(self):
  8. return self.builder.building
  9. # Abstract Builder
  10. class Builder(object):
  11. def __init__(self):
  12. self.building = None
  13. def new_building(self):
  14. self.building = Building()
  15. def build_size(self):
  16. raise NotImplementedError
  17. # Concrete Builder
  18. class BuilderHouse(Builder):
  19. def build_size(self):
  20. self.building.size = 'Big'
  21. # Product
  22. class Building(object):
  23. def __init__(self):
  24. self.size = None
  25. def __repr__(self):
  26. return 'Size: {0.size}'.format(self)
  27. # Client
  28. director = Director()
  29. director.builder = BuilderHouse()
  30. director.construct_building()
  31. building = director.get_building()
  32. print(building)
  33. ### OUTPUT ###
  34. # Size: Big

Prototype(原型模式)

说明
简化复杂而差异较小的对象的创建过程。
Prototype.png
示例代码
详细代码

  1. import copy
  2. class Book(object):
  3. def __init__(self, **info):
  4. self.__dict__.update(info)
  5. class Prototype(object):
  6. def __init__(self):
  7. self._objects = dict()
  8. def clone(self, identifier, **attrs):
  9. obj = copy.deepcopy(self._objects[identifier])
  10. obj.__dict__.update(attrs)
  11. return obj
  12. def register(self, identifier, obj):
  13. self._objects[identifier] = obj
  14. ### TEST ###
  15. prototype = Prototype()
  16. book_first_edition = Book(name='python', author='somebody', edition='first')
  17. prototype.register('a python book', book_first_edition)
  18. book_second_edition = prototype.clone('a python book', edition='second')
  19. print([{key: value} for key, value in book_first_edition.__dict__.items()])
  20. print([{key: value} for key, value in book_second_edition.__dict__.items()])
  21. ### OUTPUT ###
  22. # [{'name': 'python'}, {'edition': 'first'}, {'author': 'somebody'}]
  23. # [{'name': 'python'}, {'edition': 'second'}, {'author': 'somebody'}]

Singleton(单例)

说明
一个只允许实例化一次的类,提供全局的使用接口。
并不建议使用该模式
代码

  1. class Singleton(object):
  2. cer = True
  3. def __new__(cls):
  4. if cls.cer:
  5. cls.cer = False
  6. return super().__new__(cls)
  7. else:
  8. raise
  9. def __del__(self):
  10. self.__class__.cer = True



structural(结构模式)

结构行为是在原有对象的情况下对其进行应用。


Adapter(适配器)

说明
将拥有不同接口的对象统一成相同接口的对象。
或者为为接口作适配。
Adapter
示例代码
详细代码

  1. class Dog(object):
  2. def bark(self):
  3. return "woof!"
  4. class Human(object):
  5. def speak(self):
  6. return "'hello'"
  7. class Car(object):
  8. def make_noise(self, octane_level):
  9. return "vroom{0}".format("!" * octane_level)
  10. class Adapter(object):
  11. def __init__(self, obj, **adapted_methods):
  12. self.obj = obj
  13. self.__dict__.update(adapted_methods)
  14. def __getattr__(self, attr):
  15. return getattr(self.obj, attr)
  16. ### TEST ###
  17. objects = []
  18. objects.append(Adapter(Dog(), make_noise=dog.bark))
  19. objects.append(Adapter(Human(), make_noise=human.speak))
  20. objects.append(Adapter(Car(), make_noise=lambda: car.make_noise(3)))
  21. for obj in objects:
  22. print("A {0} goes {1}".format(obj.name, obj.make_noise()))
  23. ### OUTPUT ###
  24. # A Dog goes woof!
  25. # A Human goes 'hello'
  26. # A Car goes vroom!!!

Facade(外观)

说明
即为多个过程给予一个统一的接口。
Facade
示例代码
详细代码(这里并没有用到)

  1. class CPU(object):
  2. def startup(self):
  3. print('CPU startup.')
  4. def shutdown(self);
  5. print('CPU shutdown')
  6. class Memory(object):
  7. def startup(self):
  8. print('Memory startup.')
  9. def shutdown(self);
  10. print('Memory shutdown')
  11. class Computrt(object):
  12. def __init__(self):
  13. self.cpu = CPU()
  14. self.memory = Memory()
  15. def startup(self):
  16. self.cpu.startup()
  17. self.memory.startup()
  18. def shutdown(self);
  19. self.cpu.shutdown()
  20. self.memory.shutdown()
  21. ### TEST ###
  22. computer = Computer()
  23. computer.startup()
  24. computer.shutdown()
  25. ### OUTPUT ###
  26. # CPU startup.
  27. # Memory startup.
  28. # CPU shutdown
  29. # Memory shutdown

Decorator(装饰器)

说明
可以给对象动态的增加一些功能,装饰对象与原对象接口不变且装饰对象持有原对象的实例。
python内置的@关键字实现了本模式,以下代码仅作通用性的示范。
Decorator
示例代码
详细代码

  1. class TextTag(object):
  2. def __init__(self, text):
  3. self._text = text
  4. def render(self):
  5. return self._text
  6. class BoldWrapper(object):
  7. def __init__(self, wrapped):
  8. self._wrapped = wrapped
  9. def render(self):
  10. return "<b>{}</b>".format(self._wrapped.render())
  11. ### TEST ###
  12. simple_hello = TextTag("hello, world!")
  13. special_hello = BoldWrapper(simple_hello)
  14. print("before:", simple_hello.render())
  15. print("after:", special_hello.render())
  16. ### OUTPUT ###
  17. # before: hello, world!
  18. # after: <b>hello, world!</b>

Proxy(代理)

说明
对原有方法行为进行控制,而不修改方法本身。
注意本模式跟装饰器模式区别,装饰器是动态的,而代理是静态的。
装饰器一般会包裹整个类而保留相同接口。
而代理可以部分包裹类。
Proxy
示例代码
详细代码

  1. class SalesManager(object):
  2. def talk(self):
  3. print("Sales Manager ready to talk")
  4. class Proxy(object):
  5. def __init__(self):
  6. self.busy = 'No'
  7. self.sales = None
  8. def talk(self):
  9. print("Proxy checking for Sales Manager availability")
  10. if self.busy == 'No':
  11. self.sales = SalesManager()
  12. self.sales.talk()
  13. else:
  14. print("Sales Manager is busy")
  15. ### TEST ###
  16. p = Proxy()
  17. p.talk()
  18. p.busy = 'Yes'
  19. p.talk()
  20. ### OUTPUT ###
  21. # Proxy checking for Sales Manager availability
  22. # Sales Manager ready to talk
  23. # Proxy checking for Sales Manager availability
  24. # Sales Manager is busy

Composite(组合)

说明
处理树状结构的对象关联,如gui中各种窗口组件。
Composite
示例代码
详细代码
原代码太长了,这里做了大量简化处理。

  1. class Node(object):
  2. next_node = []
  3. def __init__(self, name):
  4. self.name = name
  5. def add_node(self, node):
  6. self.append(node)
  7. ### TEST ###
  8. window = Node('window')
  9. frame1 = Node('frame1')
  10. frame2 = Node('frame2')
  11. window.add_node(frame1)
  12. window.add_node(frame2)

Flyweight(享元)

说明
利用对象池实现了对象之间的共享,在大量创建对象的情况下可以节约内存。

示例代码
详细代码
一片森林有多颗树,但是树种类相同。

  1. class Tree:
  2. pool = dict()
  3. def __new__(cls, tree_type):
  4. obj = cls.pool.get(tree_type, None)
  5. if not obj:
  6. obj = object.__new__(cls)
  7. cls.pool[tree_type] = obj
  8. obj.tree_type = tree_type
  9. return obj
  10. def show(self, x, y):
  11. print('a {type} tree in ({x}, {y})'.format(type=self.tree_type, x=x, y=y))
  12. ### TEST ###
  13. tree = Tree('apple_tree')
  14. [tree.show(randint(0, 100), randint(0, 100)) for _ in range(10)]
  15. ### OUTPUT ###
  16. # a apple_tree tree in (32, 57)
  17. # a apple_tree tree in (39, 57)
  18. # a apple_tree tree in (86, 38)

Bridge(桥接)

说明
将抽象与实现解耦,使得二者可以独立变化
Bridge
示例代码
详细代码

  1. class DrawingAPI1(object):
  2. def draw(self):
  3. print('API1 Drawing')
  4. class DrawingAPI2(object):
  5. def draw(self):
  6. print('API2 Drawing')
  7. class Shape(object):
  8. def __init__(self,drawing_api):
  9. self._drawing_api = drawing_api
  10. def draw(self):
  11. self._drawing_api.draw()
  12. ### TEST ###
  13. shapes = (
  14. CircleShape(DrawingAPI1()),
  15. CircleShape(DrawingAPI2())
  16. )
  17. for shape in shapes:
  18. shape.draw()
  19. ### OUTPUT ###
  20. # API1 Drawing
  21. # API2 Drawing



Behavioral(行为模式)

行为模式涉及了对象与算法间的分配关系。


Strategy(策略)

说明
将算法的选择与实现分离。
Strategy
示例代码
详细代码

  1. import types
  2. class Strategy(object):
  3. def __init__(self, calculator=None):
  4. self.name = 'Strategy 0'
  5. if func is not None:
  6. self.execute = types.MethodType(calculator, self) #绑定方法
  7. def execute(self):
  8. print(self.name)
  9. def do_calculator1(self):
  10. print(self.name, 'do calculator1')
  11. def do_calculator2(self):
  12. print(self.name, 'do calculator2')
  13. ### TEST ###
  14. strat = Strategy(do_calculator1)
  15. strat.execute()
  16. ### OUTPUT ###
  17. # Strategy 0 do calculator1

Template Method(模板方法)

说明
消除冗余,对算法的部分进行定制处理。
Template Method
示例代码
详细代码

  1. ingredients = "spam eggs apple"
  2. line = '-' * 10
  3. # Skeletons
  4. def iter_elements(getter, action):
  5. for element in getter():
  6. action(element)
  7. print(line)
  8. def rev_elements(getter, action):
  9. for element in getter()[::-1]:
  10. action(element)
  11. print(line)
  12. # Getters
  13. def get_list():
  14. return ingredients.split()
  15. def get_lists():
  16. return [list(x) for x in ingredients.split()]
  17. # Actions
  18. def print_item(item):
  19. print(item)
  20. def reverse_item(item):
  21. print(item[::-1])
  22. # Makes templates
  23. def make_template(skeleton, getter, action):
  24. def template():
  25. skeleton(getter, action)
  26. return template
  27. # Create our template functions
  28. templates = [make_template(s, g, a)
  29. for g in (get_list, get_lists)
  30. for a in (print_item, reverse_item)
  31. for s in (iter_elements, rev_elements)]
  32. # Execute them
  33. for template in templates:
  34. template()
  35. ### OUTPUT ###
  36. # spam
  37. # ----------
  38. # eggs
  39. # ----------
  40. # apple
  41. # ----------
  42. # apple
  43. # ----------
  44. # eggs
  45. # ----------
  46. # spam
  47. # ----------
  48. # maps
  49. # ----------
  50. # sgge
  51. # ----------
  52. # elppa
  53. # ----------
  54. # elppa
  55. # ----------
  56. # sgge
  57. # ----------
  58. # maps
  59. # ----------
  60. # ['s', 'p', 'a', 'm']
  61. # ----------
  62. # ['e', 'g', 'g', 's']
  63. # ----------
  64. # ['a', 'p', 'p', 'l', 'e']
  65. # ----------
  66. # ['a', 'p', 'p', 'l', 'e']
  67. # ----------
  68. # ['e', 'g', 'g', 's']
  69. # ----------
  70. # ['s', 'p', 'a', 'm']
  71. # ----------
  72. # ['m', 'a', 'p', 's']
  73. # ----------
  74. # ['s', 'g', 'g', 'e']
  75. # ----------
  76. # ['e', 'l', 'p', 'p', 'a']
  77. # ----------
  78. # ['e', 'l', 'p', 'p', 'a']
  79. # ----------
  80. # ['s', 'g', 'g', 'e']
  81. # ----------
  82. # ['m', 'a', 'p', 's']
  83. # ----------

Chain of Responsibility(责任链)

说明
用于消息传递的模型,每一个节点持有下一个的应用然后将一个事件沿着链一直传递下去,直到事件被处理。
chain
示例代码
其他参考代码
详细代码

  1. class Event(object):
  2. def __init__(self, name):
  3. self.name = name
  4. def __str__(self):
  5. return self.name
  6. class Widget(object):
  7. def __init__(self, parent=None):
  8. self.parent = parent
  9. def handler(self, event):
  10. if not self._handle(event):
  11. self.parent.handler(event)
  12. def _handle(self, event):
  13. raise NotImplementedError
  14. class MainWindow(Widget):
  15. def _handle(self, event):
  16. if 'a' in str(event):
  17. print('MainWindow handled event {}'.format(event))
  18. return True
  19. else:
  20. print('in MainWindow event {} passed py'.format(event))
  21. return False
  22. class SendDialog(Widget):
  23. def _handle(self, event):
  24. if 'b' in str(event):
  25. print('SendDialog handled event {}'.format(event))
  26. return True
  27. else:
  28. print('in SendDialog event {} passed py'.format(event))
  29. return False
  30. class MsgText(Widget):
  31. def _handle(self, event):
  32. if 'c' in str(event):
  33. print('MsgText handled event {}'.format(event))
  34. return True
  35. else:
  36. print('in MsgText event {} passed py'.format(event))
  37. return False
  38. class Out(Widget):
  39. def _handle(self, event):
  40. print('event {} has no hander'.format(event))
  41. return True
  42. ### TEST ###
  43. mw = MainWindow(Out())
  44. sd = SendDialog(mw)
  45. msg = MsgText(sd)
  46. for e in 'bd':
  47. evt = Event(e)
  48. msg.handler(evt)
  49. ### OUTPUT ###
  50. # in MsgText event b passed py
  51. # SendDialog handled event b
  52. # in MsgText event d passed py
  53. # in SendDialog event d passed py
  54. # in MainWindow event d passed py
  55. # event d has no hander

Command(命令)

说明
比较容易理解的是文本编辑器中撤销操作的实现,即将操作封装成一个对象。然后维护一个命令的队列。
Command
示例代码
详细代码

  1. import os
  2. from os.path import lexists
  3. class MoveFileCommand(object):
  4. def __init__(self, src, dest):
  5. self.src = src
  6. self.dest = dest
  7. def execute(self):
  8. self.rename(self.src, self.dest)
  9. def undo(self):
  10. self.rename(self.dest, self.src)
  11. def rename(self, src, dest):
  12. print('renaming {} to {}'.format(src, dest))
  13. os.rename(src, dest)
  14. ### TEST ###
  15. command_stack = []
  16. command_stack.append(MoveFileCommand('foo.txt', 'bar.txt'))
  17. command_stack.append(MoveFileCommand('bar.txt', 'baz.txt'))
  18. for cmd in command_stack:
  19. cmd.execute()
  20. for cmd in reversed(command_stack):
  21. cmd.undo()
  22. ### OUTPUT ###
  23. # renaming foo.txt to bar.txt
  24. # renaming bar.txt to baz.txt
  25. # renaming baz.txt to bar.txt
  26. # renaming bar.txt to foo.txt

Memento(备忘录)

说明
其实叫备份模式比较好理解。
即对对象的状态进行备份和存储以使对象在需要的时刻可以恢复到之前的状态。
如实现一个回滚的操作。
Memento
示例代码
详细代码
这里用到了一点动态语言闭包的小技巧。

  1. from copy import deepcopy
  2. class Memento(object):
  3. def __init__(self, obj):
  4. state = deepcopy(obj.__dict__)
  5. def rollback():
  6. obj.__dict__.clear()
  7. obj.__dict__.update(state)
  8. self.rollback = rollback
  9. class Forgettable(object):
  10. def __init__(self, value):
  11. self.value = value
  12. def __str__(self):
  13. return self.value
  14. def commit(self):
  15. self.memo = Memento(self)
  16. def rollback(self):
  17. self.memo.rollback()
  18. ### TEST ###
  19. forget_it = Forgettable('something you cant forget')
  20. forget_it.commit()
  21. print(forget_it)
  22. forget_it.value = 'I forgot it'
  23. print(forget_it)
  24. forget_it.rollback()
  25. print(forget_it)
  26. ### OUTPUT ###
  27. # something you cant forget
  28. # I forgot it
  29. # something you cant forget

State(状态)

说明
当对象的状态改变时同时改变其行为。
State
示例代码
详细代码

  1. class State(object):
  2. def scan(self):
  3. self.pos += 1
  4. print("Scanning... Station is", self.stations[self.pos], self.name)
  5. class AmState(State):
  6. def __init__(self, radio):
  7. self.radio = radio
  8. self.stations = ["1250", "1380", "1510"]
  9. self.pos = 0
  10. self.name = "AM"
  11. def toggle_amfm(self):
  12. print("Switching to FM")
  13. self.radio.state = self.radio.fmstate
  14. class FmState(State):
  15. def __init__(self, radio):
  16. self.radio = radio
  17. self.stations = ["81.3", "89.1", "103.9"]
  18. self.pos = 0
  19. self.name = "FM"
  20. def toggle_amfm(self):
  21. print("Switching to AM")
  22. self.radio.state = self.radio.amstate
  23. class Radio(object):
  24. def __init__(self):
  25. self.amstate = AmState(self)
  26. self.fmstate = FmState(self)
  27. self.state = self.amstate
  28. def toggle_amfm(self):
  29. self.state.toggle_amfm()
  30. def scan(self):
  31. self.state.scan()
  32. ### TEST ###
  33. radio = Radio()
  34. radio.scan()
  35. radio.toggle_amfm()
  36. radio.scan()
  37. ### OUTPUT ###
  38. # Scanning... Station is 1380 AM
  39. # Switching to FM
  40. # Scanning... Station is 89.1 FM

Visitor(访问者)

说明
将数据结构及其操作解耦,用于数据结构稳定但其算法多变的系统。
Visitor

示例代码
详细代码

这个例子并不是特别好理解。类的mro是固定的结构,使用visit方法对树进行遍历,如果visitor中有处理相应节点的方法则调用。

  1. class Node(object):
  2. pass
  3. class A(Node):
  4. pass
  5. class B(Node):
  6. pass
  7. class C(A, B):
  8. pass
  9. class Visitor(object):
  10. def visit(self, node, *args, **kwargs):
  11. meth = None
  12. for cls in node.__class__.__mro__:
  13. meth_name = 'visit_' + cls.__name__
  14. meth = getattr(self, meth_name, None)
  15. if meth:
  16. break
  17. if not meth:
  18. meth = self.generic_visit
  19. return meth(node, *args, **kwargs)
  20. def generic_visit(self, node, *args, **kwargs):
  21. print('generic_visit ' + node.__class__.__name__)
  22. def visit_B(self, node, *args, **kwargs):
  23. print('visit_B ' + node.__class__.__name__)
  24. ### TEST ###
  25. a = A()
  26. b = B()
  27. c = C()
  28. visitor = Visitor()
  29. visitor.visit(a)
  30. visitor.visit(b)
  31. visitor.visit(c)
  32. ### OUTPUT ###
  33. # generic_visit A
  34. # visit_B B
  35. # visit_B C

Mediator(中介者)

说明
解决类与类之间的依赖关系中间加一层mediator来解耦。
即类与类之间存在依赖关系时通过来mediator来共享关系。
Mediator
示例代码
详细代码

  1. class Worker(object):
  2. def __init__(self, mediator):
  3. self.mediator = mediator
  4. class Worker1(Work):
  5. def work()
  6. def work_with_work2():
  7. self.mediator.work2
  8. class Worker2(Work):
  9. def work():
  10. def work_with_work1():
  11. self.mediator.work1
  12. class Mediator(object):
  13. def __init__(self):
  14. self.worker1 = Worker1(self)
  15. self.worker2 = Worker2(self)
  16. def work();
  17. self.worker1.work()
  18. self.worker2.work()

Observer(观察者)

说明
当对象变化时其依赖的对象都会收到通知并随之变化
observer
示例代码
详细代码

  1. class Subject(object):
  2. def __init__(self):
  3. self._observers = []
  4. def attach(self, observer):
  5. self._observers.append(observer)
  6. def detach(self, observer):
  7. self._observers.remove(observer)
  8. def notify(self):
  9. for observer in self._observers:
  10. observer.update(self)
  11. class MySubject(Subject):
  12. def __init__(self, name=''):
  13. super().__init__(self)
  14. self.name = name
  15. def subject_changed(self):
  16. self.notify()
  17. class Viewer1:
  18. def update(self, subject):
  19. print('Viewer1: Subject %s changed' % (subject.name,))
  20. class Viewer2:
  21. def update(self, subject):
  22. print('Viewer2: Subject %s changed' % (subject.name,))
  23. ### TEST ###
  24. subject1 = MySubject('MySubject')
  25. view1 = Viewer1()
  26. view2 = Viewer2()
  27. subject1.attach(view1)
  28. subject1.attach(view2)
  29. subject1.subject_changed()
  30. ### OUTPUT ###
  31. # Viewer1: Viewer2: Subject Mysubject changed
  32. # Viewer2: Viewer2: Subject Mysubject changed

参考

design-patterns-for-humans
《设计模式解析》
cnblog设计模式
python示例代码来源
精通Python设计模式(这书挺烂的,并不建议看,拿了一部分源码参考)


添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注