|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +# @Author : ydf |
| 3 | +# @Time : 2019/10/9 0009 9:39 |
| 4 | + |
| 5 | +"""重要程度 ☆☆☆ |
| 6 | +当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 |
| 7 | +有时,我们希望在一个对象的状态改变时更新另外一组对象。 |
| 8 | +
|
| 9 | +说这么多抽象的概念,说点具体的就是以日志为例,有人把print当做日志用,里面的区别相当大,日志不仅可以有streamhandler和filehandler,还有mailhandler httphandler 等几亿种自定义handler。logger debug时候自动触发各种handler的emit方法。 |
| 10 | +用不会日志不理解日志,对logger addHandler各种handler懵逼不知道在干嘛,最主要是不懂观察者模式造成的。 |
| 11 | +希望举得例子是接近真实有意义,下面简单使用观察者模式重新模拟实现一个伪日志包。 |
| 12 | +""" |
| 13 | +import abc |
| 14 | +from monkey_print2 import print |
| 15 | + |
| 16 | + |
| 17 | +class AbstractHandler(metaclass=abc.ABCMeta): |
| 18 | + @abc.abstractmethod |
| 19 | + def emit(self, record): |
| 20 | + pass |
| 21 | + |
| 22 | + |
| 23 | +class Logger: |
| 24 | + def __init__(self, logger_name): |
| 25 | + self.name = logger_name |
| 26 | + self.handlers = [] |
| 27 | + |
| 28 | + def add_handler(self, handler): |
| 29 | + self.handlers.append(handler) |
| 30 | + |
| 31 | + def log(self, record: str): |
| 32 | + for hr in self.handlers: |
| 33 | + hr.emit(f'{self.name} -- {record}') |
| 34 | + |
| 35 | + |
| 36 | +class StreamHandler(AbstractHandler): |
| 37 | + def emit(self, record): |
| 38 | + print(f' {record} 控制台打印') |
| 39 | + |
| 40 | + |
| 41 | +class FileHandler(AbstractHandler): |
| 42 | + def emit(self, record): |
| 43 | + print(f' {record} 文件写入') # 只是为了演示写入文件,用print模拟的伪实现。希望要搞清楚这里的目的不是print。 |
| 44 | + |
| 45 | + |
| 46 | +class MailHandler(AbstractHandler): |
| 47 | + def emit(self, record): |
| 48 | + print(f' {record} 发邮件给某人') # 只是为了演示发邮件,用print模拟的伪实现。希望要搞清楚这里的目的不是print。 |
| 49 | + |
| 50 | + |
| 51 | +class DingdingHandler(AbstractHandler): |
| 52 | + def emit(self, record): |
| 53 | + print(f' {record} 钉钉机器人将这句话发给群里') # 只是为了演示发钉钉机器人消息,用print模拟的伪实现。希望要搞清楚这里的目的不是print。 |
| 54 | + |
| 55 | + |
| 56 | +if __name__ == '__main__': |
| 57 | + logger1 = Logger('a') |
| 58 | + logger1.add_handler(StreamHandler()) |
| 59 | + logger1.add_handler(FileHandler()) |
| 60 | + logger1.add_handler(MailHandler()) |
| 61 | + logger1.log('啦啦啦啦啦啦') |
| 62 | + |
| 63 | + logger2 = Logger('b') |
| 64 | + logger2.add_handler(StreamHandler()) |
| 65 | + logger2.add_handler(DingdingHandler()) |
| 66 | + logger2.log('哈哈哈哈哈哈') |
| 67 | + |
| 68 | + """ |
| 69 | + 可以看到日志非常灵活,可以按需选择几个handler,例如日志a会 控制台打印版 写入文件 发邮件,日志b控制台打印 发钉钉消息。 |
| 70 | + "D:/coding2/python36patterns/行为型模式-观察者模式.py:36" 10:00:19 a -- 啦啦啦啦啦啦 控制台打印 |
| 71 | + "D:/coding2/python36patterns/行为型模式-观察者模式.py:40" 10:00:19 a -- 啦啦啦啦啦啦 文件写入 |
| 72 | + "D:/coding2/python36patterns/行为型模式-观察者模式.py:45" 10:00:19 a -- 啦啦啦啦啦啦 发邮件给某人 |
| 73 | + "D:/coding2/python36patterns/行为型模式-观察者模式.py:36" 10:00:19 b -- 哈哈哈哈哈哈 控制台打印 |
| 74 | + "D:/coding2/python36patterns/行为型模式-观察者模式.py:49" 10:00:19 b -- 哈哈哈哈哈哈 钉钉机器人将这句话发给群里 |
| 75 | + """ |
0 commit comments