详解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正则表达式修复网站文章字体不统一的解决方法
Feb 21 Python
python通过socket查询whois的方法
Jul 18 Python
Python对列表去重的多种方法(四种方法)
Dec 05 Python
Sanic框架蓝图用法实例分析
Jul 17 Python
Python常见内置高效率函数用法示例
Jul 31 Python
Python多线程处理实例详解【单进程/多进程】
Jan 30 Python
基于python实现百度翻译功能
May 09 Python
Django实现简单网页弹出警告代码
Nov 15 Python
关于win10在tensorflow的安装及在pycharm中运行步骤详解
Mar 16 Python
解决Jupyter notebook更换主题工具栏被隐藏及添加目录生成插件问题
Apr 20 Python
Python学习笔记之装饰器
Aug 06 Python
Python编写冷笑话生成器
Apr 20 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
《魔兽争霸3:重制版》更新 多项视觉效果调整
2020/05/04 魔兽争霸
自制短波长线天线频率预选器 - 成功消除B2K之流的镜像
2021/03/02 无线电
php反射应用示例
2014/02/25 PHP
PHPAnalysis中文分词类详解
2014/06/13 PHP
Aster vs Newbee BO3 第二场2.18
2021/03/10 DOTA
IE中jquery.form中ajax提交没反应解决方法分享
2012/09/11 Javascript
关于Javascript加载执行优化的研究报告
2014/12/16 Javascript
javascript 判断整数方法分享
2014/12/16 Javascript
javascript设置和获取cookie的方法实例详解
2016/01/05 Javascript
javascript+css3开发打气球小游戏完整代码
2017/11/28 Javascript
Vue-cli@3.0 插件系统简析
2018/09/05 Javascript
Js和VUE实现跑马灯效果
2020/05/25 Javascript
[15:20]DOTA2亚洲邀请赛总决赛开幕式表演:羽泉献唱
2017/04/05 DOTA
Python闭包实现计数器的方法
2015/05/05 Python
Python实现自动登录百度空间的方法
2017/06/10 Python
python 生成器协程运算实例
2017/09/04 Python
详解Pytorch 使用Pytorch拟合多项式(多项式回归)
2018/05/24 Python
Python简单获取网卡名称及其IP地址的方法【基于psutil模块】
2018/05/24 Python
anaconda如何查看并管理python环境
2019/07/05 Python
利用python中集合的唯一性实现去重
2020/02/11 Python
Python  word实现读取及导出代码解析
2020/07/09 Python
python中requests模拟登录的三种方式(携带cookie/session进行请求网站)
2020/11/17 Python
使用phonegap查找联系人的实现方法
2017/03/31 HTML / CSS
Vans英国官方网站:美国南加州的原创极限运动潮牌
2017/01/20 全球购物
乌克兰网上珠宝商店:GoldSoveren
2020/03/31 全球购物
西班牙购买隐形眼镜、眼镜和太阳镜网站:Lentiamo.es
2020/06/11 全球购物
教导处工作制度
2014/01/18 职场文书
领导干部考察材料
2014/02/08 职场文书
暑假家长评语大全
2014/04/17 职场文书
董事长助理工作职责
2014/06/08 职场文书
党员学习群众路线心得体会
2014/11/04 职场文书
写给老师的保证书
2015/05/09 职场文书
消防宣传标语大全
2015/08/03 职场文书
职工的安全责任书范文!
2019/07/02 职场文书
详解PHP设计模式之依赖注入模式
2021/05/25 PHP
Nginx设置HTTPS的方法步骤 443证书配置方法
2022/03/21 Servers