详解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利用elaphe制作二维条形码实现代码
May 25 Python
Python单例模式的两种实现方法
Aug 14 Python
Python实现简易Web爬虫详解
Jan 03 Python
python 列表删除所有指定元素的方法
Apr 19 Python
pygame游戏之旅 创建游戏窗口界面
Nov 20 Python
使用Django连接Mysql数据库步骤
Jan 15 Python
Python 经典算法100及解析(小结)
Sep 13 Python
np.random.seed() 的使用详解
Jan 14 Python
python使用Geany编辑器配置方法
Feb 21 Python
Python 存取npy格式数据实例
Jul 01 Python
python 使用OpenCV进行简单的人像分割与合成
Feb 02 Python
PyQt5 QThread倒计时功能的实现代码
Apr 02 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文本数据库的搜索方法
2006/10/09 PHP
Win2003服务器安全加固设置--进一步提高服务器安全性
2007/05/23 PHP
php 什么是PEAR?
2009/03/19 PHP
浅析php中三个等号(===)和两个等号(==)的区别
2013/08/06 PHP
Laravel 自带的Auth验证登录方法
2019/09/30 PHP
javascript String 的扩展方法集合
2008/06/01 Javascript
Jquery为单选框checkbox绑定单击click事件
2012/12/18 Javascript
jQuery学习笔记(1)--用jQuery实现异步通信(用json传值)具体思路
2013/04/08 Javascript
利用js实现遮罩以及弹出可移动登录窗口
2013/07/08 Javascript
js简单工厂模式用法实例
2015/06/30 Javascript
JavaScript 2048 游戏实例代码(简单易懂)
2016/03/25 Javascript
Angularjs使用directive自定义指令实现attribute继承的方法详解
2016/08/05 Javascript
Vue.js每天必学之构造器与生命周期
2016/09/05 Javascript
Angularjs按需查询实例代码
2017/10/30 Javascript
nodejs使用express获取get和post传值及session验证的方法
2017/11/09 NodeJs
JS改变页面颜色源码分享
2018/02/24 Javascript
vue微信分享插件使用方法详解
2020/02/18 Javascript
[01:07:22]2014 DOTA2华西杯精英邀请赛 5 24 DK VS VG加赛
2014/05/26 DOTA
Python使用Selenium+BeautifulSoup爬取淘宝搜索页
2018/02/24 Python
Python3.5面向对象编程图文与实例详解
2019/04/24 Python
Python 虚拟空间的使用代码详解
2019/06/10 Python
python+opencv像素的加减和加权操作的实现
2019/07/14 Python
django框架模型层功能、组成与用法分析
2019/07/30 Python
基于Python正确读取资源文件
2020/09/14 Python
python3中数组逆序输出方法
2020/12/01 Python
HTML5 CSS3给网站设计带来出色效果
2009/07/16 HTML / CSS
英国领先的珍珠首饰品牌:Orchira
2016/09/11 全球购物
Dr. Martens马汀博士官网:马丁靴始祖品牌
2016/10/15 全球购物
Linux Interview Questions For software testers
2012/06/02 面试题
会计专业自荐信
2013/12/02 职场文书
幼儿园校车司机的岗位职责
2014/01/30 职场文书
竞选大队委员演讲稿
2014/04/28 职场文书
酒店开业庆典策划方案
2014/05/28 职场文书
大学生干部培训心得体会
2016/01/06 职场文书
Redis可视化客户端小结
2021/06/10 Redis
使用Python开发贪吃蛇游戏 SnakeGame
2022/04/30 Python