详解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 相关文章推荐
python3学习笔记之多进程分布式小例子
Feb 13 Python
python如何去除字符串中不想要的字符
Jul 05 Python
解决Python3 被PHP程序调用执行返回乱码的问题
Feb 16 Python
python 计算一个字符串中所有数字的和实例
Jun 11 Python
Python Numpy计算各类距离的方法
Jul 05 Python
Python+selenium点击网页上指定坐标的实例
Jul 05 Python
10分钟用python搭建一个超好用的CMDB系统
Jul 17 Python
python实现文件的分割与合并
Aug 29 Python
Python3.6 + TensorFlow 安装配置图文教程(Windows 64 bit)
Feb 24 Python
Python3标准库之dbm UNIX键-值数据库问题
Mar 24 Python
keras slice layer 层实现方式
Jun 11 Python
Python 日期与时间转换的方法
Aug 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手册及PHP编程标准
2006/12/17 PHP
PHP5.3的垃圾回收机制(动态存储分配方案)深入理解
2012/12/10 PHP
php中mail函数发送邮件失败的解决方法
2014/12/24 PHP
PHP实现简单汉字验证码
2015/07/28 PHP
理解php依赖注入和控制反转
2016/05/11 PHP
php校验公钥是否可用的实例方法
2019/09/17 PHP
飞鱼(shqlsl) javascript作品集
2006/12/16 Javascript
{}与function(){}选用空对象{}来存放keyValue
2012/05/23 Javascript
jquery如何改变html标签的样式(两种实现方法)
2013/01/16 Javascript
关于jQuery对象数据缓存Cache原理以及jQuery.data详解
2013/04/07 Javascript
Jqgrid表格随窗口大小改变而改变的简单实例
2013/12/28 Javascript
jQuery插件FusionCharts实现的3D柱状图效果实例【附demo源码下载】
2017/03/03 Javascript
jQuery弹出窗口简单实现代码
2017/03/09 Javascript
jQuery EasyUI tree增加搜索功能的实现方法
2017/04/27 jQuery
jQuery简单绑定单个事件的方法示例
2017/06/10 jQuery
JS实现的简单下拉框联动功能示例
2018/05/11 Javascript
vue打包使用Nginx代理解决跨域问题
2018/08/27 Javascript
JS实现从对象获取对象中单个键值的方法示例
2019/06/05 Javascript
vue+express+jwt持久化登录的方法
2019/06/14 Javascript
vuex实现数据状态持久化
2019/11/11 Javascript
python创建只读属性对象的方法(ReadOnlyObject)
2013/02/10 Python
Python映射拆分操作符用法实例
2015/05/19 Python
日常整理python执行系统命令的常见方法(全)
2015/10/22 Python
Python实现查找匹配项作处理后再替换回去的方法
2017/06/10 Python
python放大图片和画方格实现算法
2018/03/30 Python
在Python 字典中一键对应多个值的实例
2019/02/03 Python
django项目中使用云片网发送短信验证码的实现
2021/01/19 Python
发现两个有趣的CSS3动画效果
2013/08/14 HTML / CSS
美国鲜花递送:UrbanStems
2021/01/04 全球购物
什么是Oracle的后台进程background processes?都有哪些后台进程?
2012/04/26 面试题
宿舍保安职务说明书
2014/02/25 职场文书
合伙经营协议书范本
2014/04/18 职场文书
商务专员岗位职责范本
2014/06/29 职场文书
优秀教研组申报材料
2014/12/26 职场文书
离职证明格式样本
2015/06/12 职场文书
四十年同学聚会致辞
2015/07/28 职场文书