源码地址:https://github.com/weilanhanf/PythonDesignPatterns

说明:

策略指的就是为了达到某一目的而采取的手段或者方法。为了实现软件设计咪表,对象可能会用到多种多样的算法。这些算法甚至会经常改变。如果将这些算法都硬编码到对象中,将会使得对象本身变得臃肿不堪,而且有时候支持不同的算法也是一个性能负担。策略模式很好的实现了在运行时根据需要透明的更改对象的算法和将算法与本身对象解耦,从而避免出现上述两个问题。

因此策略模式可以定义为: 定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法可以独立于使用它的客户变化。每一个封装算法的类称之为策略(Strategy)类,策略模式提供了一种可插入式(Pluggable)算法的实现方案

策略模式的结构

策略模式包含以下3个角色: Context(环境类) Strategy(抽象策略类) ConcreteStrategy(具体策略类)

实例:

假设某司维护着一些客户资料,需要在该司有新产品上市或者举行新活动时通知客户。现通知客户的方式有两种:短信通知、邮件通知。应如何设计该系统的客户通知部分?为解决该问题,我们先构造客户类,包括客户常用的联系方式和基本信息,同时也包括要发送的内容。

class customer:
customer_name=""
snd_way=""
info=""
phone=""
email=""
def setPhone(self,phone):
self.phone=phone
def setEmail(self,mail):
self.email=mail
def getPhone(self):
return self.phone
def getEmail(self):
return self.email
def setInfo(self,info):
self.info=info
def setName(self,name):
self.customer_name=name
def setBrdWay(self,snd_way):
self.snd_way=snd_way
def sndMsg(self):
self.snd_way.send(self.info) #snd_way向客户发送信息的方式,该方式置为可设,即可根据业务来进行策略的选择。
#发送方式构建如下:
class msgSender:
dst_code=""
def setCode(self,code):
self.dst_code=code
def send(self,info):
pass class emailSender(msgSender):
def send(self,info):
print("EMAIL_ADDRESS:%s EMAIL:%s"%(self.dst_code,info)) class textSender(msgSender):
def send(self,info):
print("TEXT_CODE:%s EMAIL:%s"%(self.dst_code,info))

#业务场景中将发送方式作为策略
if __name__=="__main__":
customer_x=customer()
customer_x.setName("CUSTOMER_X")
customer_x.setPhone("")
customer_x.setEmail("customer_x@xmail.com")
customer_x.setInfo("Welcome to our new party!")
text_sender=textSender()
text_sender.setCode(customer_x.getPhone())
customer_x.setBrdWay(text_sender)
customer_x.sndMsg()
mail_sender=emailSender()
mail_sender.setCode(customer_x.getEmail())
customer_x.setBrdWay(mail_sender)
customer_x.sndMsg()

打印结果

TEXT_CODE:10023456789 EMAIL:Welcome to our new party!
EMAIL_ADDRESS:customer_x@xmail.com EMAIL:Welcome to our new party!

模式优点

提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为 提供了管理相关的算法族的办法 提供了一种可以替换继承关系的办法 可以避免多重条件选择语句 提供了一种算法的复用机制,不同的环境类可以方便地复用策略类

模式缺点

客户端必须知道所有的策略类,并自行决定使用哪一个策略类 将造成系统产生很多具体策略类 无法同时在客户端使用多个策略类

模式适用环境

一个系统需要动态地在几种算法中选择一种 避免使用难以维护的多重条件选择语句 不希望客户端知道复杂的、与算法相关的数据结构,提高算法的保密性与安全性

另外:

仔细比较一下桥接模式和策略模式,如果把策略模式的Context设计成抽象类和实现类的方式,那么策略模式和桥接模式就可以划等号了。从类图看上去,桥接模式比策略模式多了对一种角色(抽象角色)的抽象。二者结构的高度同构,也只能让我们从使用意图上去区分两种模式:桥接模式解决抽象角色和实现角色都可以扩展的问题;而策略模式解决算法切换和扩展的问题。

python-策略模式的更多相关文章

  1. 设计模式(Python)-策略模式

    本系列文章是希望将软件项目中最常见的设计模式用通俗易懂的语言来讲解清楚,并通过Python来实现,每个设计模式都是围绕如下三个问题: 为什么?即为什么要使用这个设计模式,在使用这个模式之前存在什么样的 ...

  2. Python策略模式实现源码分享

    1.让一个对象的某个方法可以随时改变,而不用更改对象的代码 2.对于动态类型的Python语言,不需要定义接口 3.基本的实现方法:用类作为参数传递 例如: 12_eg3.py class Movea ...

  3. [Python模式]策略模式

    策略模式 定义了算法族,分别封装起来,让它们之间可以互相替换.此模式让算法的变化独立于使用算法的客户. 作为动态语言,Python实现策略模式非常容易,只要所有算法提供相同的函数即可. import ...

  4. Python 中的设计模式详解之:策略模式

    虽然设计模式与语言无关,但这并不意味着每一个模式都能在每一门语言中使用.<设计模式:可复用面向对象软件的基础>一书中有 23 个模式,其中有 16 个在动态语言中“不见了,或者简化了”. ...

  5. 【经典案例】Python详解设计模式:策略模式

    完成一项任务往往有多种方式,我们将其称之为策略. 比如,超市做活动,如果你的购物积分满1000,就可以按兑换现金抵用券10元,如果购买同一商品满10件,就可以打9折,如果如果购买的金额超过500,就可 ...

  6. python设计模式第九天【策略模式】

    1. 定义 对一系列算法进行封装,为所有算法定义一个抽象的算法接口,可以平滑的进行算法切换 2. 策略模式的UML图 3.代码实现 #!/usr/bin/env python #! _*_ codin ...

  7. Python 设计模式--策略模式

    策略模式(Strategy Pattern) 策略模式是一种与行为相关的设计模式,允许你在运行时根据指定的上下文确定程序的动作.可以在两个类中封装不同的算法,并且在程序运行时确定到底执行哪中策略. 特 ...

  8. 大话设计模式Python实现-策略模式

    策略模式(Strategy Pattern):它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. 下面是一个商场活动的实现 #!/usr/bin/e ...

  9. python实现策略模式

    python实现策略模式 原文地址 1.策略模式概述 策略模式:定义一系列算法,把它们一一封装起来,并且使它们之间可以相互替换.此模式让算法的变化不会影响到使用算法的客户. 电商领域有个使用“策略”模 ...

  10. 架构师修炼之设计模式 - 策略模式(Strategy) 【Python与C#实现】

    程序员,我为你祝福 愿你有一个灿烂的前程 愿你有情人终成眷属 愿你在尘世获得幸福 我只想成为架构师,走遍江湖! 目录 模式定义 模式分类 模式结构 实例(C#与Python版) 优点 缺点 使用场景 ...

随机推荐

  1. Yii2 Apache + Nginx 路由重写

    一.什么是路由重写 原本的HTTP访问地址: www.test.com/index.php?r=post/view&id=100 表示这个请求将由PostController 的 action ...

  2. Unity C# .Net List 优化点

    Unity C# .Net List 优化点 已知长度 则初始化指定长度 调用多次Remove会导致内存浪费 调用TrimExcess释放多余内存 List代码实现原理 使用数组保存泛型数据 代码 L ...

  3. async await 的执行

    async await的执行 注意:本次代码仅在 Chrome 73 下进行测试. start 不了解 async await 的,先去看阮一峰老师的文章async 函数. 先来看一道头条的面试题,这 ...

  4. Oracle的卸载过程步骤

    用Oracle自带的卸载程序不能从根本上卸载Oracle,从而为下次的安装留下隐患,那么怎么才能完全卸载Oracle呢?那就是直接注册表清除,步骤如下: 1. 开始->设置->控制面板-& ...

  5. Mysql的优化一则

    目的在于这么一个sql语句: SELECT w.* FROM wallpaper w inner join wallpaper_category_relation r ON w.wallpaper_i ...

  6. freerdp服务器共享屏幕,skype lync终端显示黑屏的原因分析

    问题描述:freerdp支持远程桌面共享协议rdp,使用freerdp与skype终端进行远程桌面共享时.发送1080p 视频数据时 skype终端显示黑屏 经过分析,发现rdp协商参数大于一定值时, ...

  7. Ubuntu 16.04 服务器上配置使用 Docker

    Docker基础概念 在使用Docker之前,我们先了解下几个Docker的核心概念 Docker Daemon Docker引擎,就是运行在后台的一个守护进程,在我们启动它之后,我们就可以通过Doc ...

  8. 【nodejs】文件上传demo实现

    文件结构: index.js var server = require('./server.js'); var router = require('./router.js'); var request ...

  9. vue修改对象属性值视图上没有更新

    data(){ return { obj:{ name:' ' } } } 方法一: this.$set(this.obj, 'name', '新的值'); 方法二; Vue.set(vm.obj, ...

  10. 第三方登录:微信扫码登录(OAuth2.0)

    1.OAuth2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户提供 ...