详解Python设计模式编程中观察者模式与策略模式的运用


Posted in Python onMarch 02, 2016

观察者模式

观察者模式:又叫发布订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时,会通知所有观察者对象,是他们能自动更新自己。

代码结构

class Topic(object):
  """主题类。保存所有观察者实例的引用,每个主题都可以有很多观察者
  可以增加和删除观察者"""
  def __init__(self):
    self.obs = []

  def Attach(self, ob):
    self.obs.append(ob)

  def Detach(self, ob):
    self.obs.remove(ob)

  def Notify(self):
    for ob in self.obs:
      ob.Update()

class Observer(object):
  """抽象观察者类,收到主题的变更通知时,更新自己"""
  def Update(self):
    raise NotImplementedError()

class ConcreteTopic(object):
  """一个具体主题"""
  def __init__(self):
    self.state = None

  def ChangeState(self, newState):
    self.state = newState
    self.Notify()

class ConcreteObserver(object):
  """一个具体监听类"""
  def __init__(self, topic):
    self.topic = topic

  def Update(self):
    print self.topic.state

def client():
  topic = ConcreteTopic()
  topic.Attach(ConcreteObserver(topic))

  topic.ChangeState('New State')

众多MQ中间件都是采用这种模式的思想来实现的。

观察者模式可以让主题和观察者之间解耦,互相之间尽可能少的依赖。不过抽象主题和抽象观察者之间还是有耦合的。

策略模式
策略模式: 定义了算法家族,分别封装起来,让他们之间可以互相替换。此模式让算法的变化不影响使用算法的客户。

代码框架

class Strategy(object):
  """抽象算法类"""
  def AlgorithmInterface(self):
    raise NotImplementedError()

class ConcreteStrategyA(Strategy):
  def AlgorithmInterface(self):
    print '算法A'

class ConcreteStrategyB(Strategy):
  def AlgorithmInterface(self):
    print '算法B'

class Context(object):
  """上下文,作用就是封装策略的实现细节,用户只需要知道有哪些策略可用"""
  def __init__(self, strategy):
    # 初始化时传入具体的策略实例
    self.strategy = strategy

  def ContextInterface(self):
    # 负责调用具体的策略实例的接口
    self.strategy.AlgorithmInterface()

def client(cond):
  # 策略模式的使用演示
  # 用户只需要根据不同的条件,将具体的算法实现类传递给Context,
  # 然后调用Context暴露给用户的接口就行了。
  if cond == 'A':
    context = Context(ConcreteStrategyA())
  elif cond == 'B':
    context = Context(ConcreteStrategyB())

  result = context.ContextInterface()

策略模式解决那类问题

在回答这个问题之前,先说下对策略模式的使用方式的感觉。上面的client函数,怎么看起来就像是简单工厂模式中的工厂函数呢?确实如此,实际上策略模式可以和简工厂模式结合起来,将更多细节封装在策略模式内部,让使用者更容易的使用。

那么策略模式和简单工厂模式有什么不同呢?策略模式中的算法是用来解决同一个问题的,根据时间、条件不同,算法的具体细节有差异,但最终解决的是同一个问题。在需求分析过程中,当听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式来处理这种变化的可能性。

缺点

使用者需要知道每一种策略的具体含义,并负责选择策略
改进

结合简单工厂模式,将策略选择封装在Context内部,解放client:

class Context(object):
  def __init__(self, cond):
    if cond == 'A':
      self.strategy = Context(ConcreteStrategyA())
    elif cond == 'B':
      self.strategy = Context(ConcreteStrategyB())

  def ContextInterface(self):
    self.strategy.AlgorithmInterface()


def client(cond):
  context = Context(cond)
  result = context.ContextInterface()

改进后的遗留问题

每次需要增加新的策略时,就需要修改Context的构造函数,增加一个新的判断分支。

Python 相关文章推荐
Python 字典dict使用介绍
Nov 30 Python
Python的math模块中的常用数学函数整理
Feb 04 Python
小米5s微信跳一跳小程序python源码
Jan 08 Python
python爬虫正则表达式之处理换行符
Jun 08 Python
win7下python3.6安装配置方法图文教程
Jul 31 Python
Django CBV类的用法详解
Jul 26 Python
PyTorch中常用的激活函数的方法示例
Aug 20 Python
在 Python 中接管键盘中断信号的实现方法
Feb 04 Python
python实现滑雪游戏
Feb 22 Python
Python通过Tesseract库实现文字识别
Mar 05 Python
Python在字符串中处理html和xml的方法
Jul 31 Python
python 使用xlsxwriter循环向excel中插入数据和图片的操作
Jan 01 Python
Python设计模式编程中解释器模式的简单程序示例分享
Mar 02 #Python
分析Python中设计模式之Decorator装饰器模式的要点
Mar 02 #Python
实例解析Python设计模式编程之桥接模式的运用
Mar 02 #Python
Python随机生成带特殊字符的密码
Mar 02 #Python
Python设计模式编程中Adapter适配器模式的使用实例
Mar 02 #Python
Python打造出适合自己的定制化Eclipse IDE
Mar 02 #Python
设计模式中的原型模式在Python程序中的应用示例
Mar 02 #Python
You might like
php做下载文件的实现代码及文件名中乱码解决方法
2011/02/03 PHP
php提示Failed to write session data错误的解决方法
2014/12/17 PHP
PHP基于回溯算法解决n皇后问题的方法示例
2017/11/07 PHP
laravel 框架实现无限级分类的方法示例
2019/10/31 PHP
phpstudy隐藏index.php的方法
2020/09/21 PHP
WebGame《逆转裁判》完整版 代码下载(1月24日更新)
2007/01/29 Javascript
使用jquery hover事件实现表格的隔行换色功能示例
2013/09/03 Javascript
javascript计时器事件使用详解
2014/01/07 Javascript
Javascript中的关键字和保留字整理
2014/10/16 Javascript
基于javascript实现图片预加载
2016/01/05 Javascript
IE8 内存泄露(内存一直增长 )的原因及解决办法
2016/04/06 Javascript
SWFUpload多文件上传及文件个数限制的方法
2016/05/31 Javascript
vuejs2.0实现一个简单的分页示例
2017/02/22 Javascript
React.js中常用的ES6写法总结(推荐)
2017/05/09 Javascript
详解通过JSON数据使用VUE.JS
2017/05/26 Javascript
JS+Ajax实现百度智能搜索框
2017/08/04 Javascript
react中实现搜索结果中关键词高亮显示
2018/07/31 Javascript
Webstorm2016使用技巧(SVN插件使用)
2018/10/29 Javascript
详解关闭令人抓狂的ESlint 语法检测配置方法
2019/10/28 Javascript
微信小程序开发数据缓存基础知识辨析及运用实例详解
2020/11/06 Javascript
[01:33:25]DOTA2-DPC中国联赛 正赛 Elephant vs IG BO3 第一场 1月24日
2021/03/11 DOTA
Python使用dict.fromkeys()快速生成一个字典示例
2019/04/24 Python
django框架实现模板中获取request 的各种信息示例
2019/07/01 Python
Python re 模块findall() 函数返回值展现方式解析
2019/08/09 Python
python实现把两个二维array叠加成三维array示例
2019/11/29 Python
理肤泉英国官网:La Roche-Posay英国
2019/01/14 全球购物
介绍一下HTTP、HTTPS和SSL
2012/12/16 面试题
linux面试题参考答案(9)
2016/01/29 面试题
优秀应届生推荐信
2013/11/09 职场文书
妇产医师自荐信
2014/01/29 职场文书
老人祝寿主持词
2014/03/28 职场文书
副总经理任命书
2014/06/05 职场文书
继承权公证书范本
2015/01/23 职场文书
公司财务人员岗位职责
2015/04/14 职场文书
2015年小学远程教育工作总结
2015/07/28 职场文书
MySQL transaction事务安全示例讲解
2022/06/21 MySQL