预备知识:

开放封闭原则(Open-Closed Principle OCP)

Software entities(classes,modules,functions etc) should open for extension ,but close for modification.

所谓开放封闭原则就是软件实体应该对扩展开放,而对修改封闭。开放封闭原则是所有面向对象原则的核心。

软件设计本身所追求的目标就是封装变化,降低耦合,而开放封闭原则正是对这一目标的最直接体现。

对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。

对修改封闭,意味着类一旦设计完成,就可以独立其工作,而不要对类尽任何修改。

单一职责原则:(SRP:Single responsibility principle)
又称单一功能原则,面向对象五个基本原则(SOLID)之一。它规定一个类应该只有一个发生变化的原因。
所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。

以上,是抄得。

ok, 故事开始。

从去年开始,我们公司搞起了O2O开放平台。提供了O2O各个语言版本的基础库,比如c# php java python等.

随着时间的推移,接入开放平台的企业越来越多,使用各种语言的版本。

那么,我们写代码模拟这个过程。

写之前,介绍一下python的“属性”。

为什么要介绍这个东西,因为我之前是个c#程序猿,用得最多的就是这货。

在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改:

s = Student()
s.score = 9999

这显然不合逻辑。为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数:

class Student(object):def get_score(self):return self._scoredef set_score(self, value):if not isinstance(value, int):raise ValueError('score must be an integer!')if value < 0 or value > 100:raise ValueError('score must between 0 ~ 100!')self._score = value

现在,对任意的Student实例进行操作,就不能随心所欲地设置score了:

>>> s = Student()
>>> s.set_score(60) # ok! >>> s.get_score() 60 >>> s.set_score(9999) Traceback (most recent call last): ... ValueError: score must between 0 ~ 100! 

但是,上面的调用方法又略显复杂,没有直接用属性这么直接简单。

有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?对于追求完美的Python程序员来说,这是必须要做到的!

还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的:

class Student(object):@propertydef score(self):return self._score@score.setterdef score(self, value):if not isinstance(value, int):raise ValueError('score must be an integer!')if value < 0 or value > 100:raise ValueError('score must between 0 ~ 100!')self._score = value

>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60) >>> s.score # OK,实际转化为s.get_score() 60 >>> s.score = 9999 Traceback (most recent call last): ... ValueError: score must between 0 ~ 100!

就是这么好用(当然,比起c#来说,还是有点丑陋,为什么我就不说了..毕竟php是世界上最好的语言)

ok,现在开始开放平台的接入工作。于是我们写了如下代码:
# -*- coding: utf-8 -*-

class OpenService(object):@propertydef language(self):return self.__language@language.setterdef language(self, value):self.__language = valuedef __init__(self):self.__language = 'csharp'def attack_cities(self):if self.__language == 'python':print '攻城师 苦逼兮兮, 写python'elif self.__language == 'java':print '攻城师 苦逼兮兮, 写java'elif self.__language == 'php':print '攻城师 屌屌的, 写php,毕竟php是世界上最好的语言'elif self.__language == 'c#':print '攻城师 苦逼兮兮, 写c#'if __name__ == "__main__":open_service = OpenService()print '某公司1开始对接python...'open_service.language = 'python'open_service.attack_cities()print '某公司2开始对接java...'open_service.language = 'java'open_service.attack_cities()print '某公司3开始对接php...'open_service.language = 'php'open_service.attack_cities()print '某公司4开始对接c#...'open_service.language = 'c#'open_service.attack_cities()

PM一声令下,公司1,2,3,4 纷纷对接开放平台.

过了一段时间,触宝又增加了,c++,c,vb.....等各种语言的开放平台sdk...那么怎么办呢?很简单..在attack_cities 方法里加更多的if else 判读呗...于是代码的坏味道出现了....1. 过长的if else 是明显的坏味道..2. 写代码是个复杂的过程,全部写在一个方法里...这个方法明显职责过重.违背了本文一开始的单一职责原则。

是时候重构了,当当当当,静态工厂模式善良登场。

简单工厂模式

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
该模式中包含的角色及其职责
工厂(Creator)角色
简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
抽象产品(Product)角色
简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色
是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。


ok,上面也是我抄得。

知道了定义,我们就要对我们的场景做出抽象。变化的部分是语言,以及攻城狮如何攻城。那么我们就需要设计一个语言基类。带有攻城的抽象方法。然后需要定义一个工厂,根据不同的需求产出不同的语言攻城狮。当然,为了使用抽象方法,我们必须引入卫生巾模块abc这样的话,子类如果不实现基类的抽象方法,会抛出not implement 异常(我猜是这个异常)

如下:
import abc
class OpenServiceFactory(object):languageInstance = Nonedef __init__(self):pass@staticmethoddef CreateLanguage(language):if language == 'c#':OpenServiceFactory.languageInstance = CsharpLanguage()elif language == 'java':OpenServiceFactory.languageInstance = JavaLanguage()elif language == 'php':OpenServiceFactory.languageInstance = PHPLanguage()elif language == 'python':OpenServiceFactory.languageInstance = PythonLanguage()return OpenServiceFactory.languageInstanceclass LanageBase(object):@abc.abstractmethoddef att_cities(self):passclass CsharpLanguage(LanageBase):def att_cities(self):print '攻城师 苦逼兮兮, 写c#'class JavaLanguage(LanageBase):def att_cities(self):print '攻城师 苦逼兮兮, 写java'class PHPLanguage(LanageBase):def att_cities(self):print '攻城师 屌屌的, 写php,毕竟php是世界上最好的语言'class PythonLanguage(LanageBase):def att_cities(self):print '攻城师 苦逼兮兮, 写python'

测试:

if __name__ == "__main__":print '简单工厂思密达'print '某公司1开始对接python...'open_service = OpenServiceFactory.CreateLanguage('python')open_service.att_cities()print '某公司2开始对接java...'open_service = OpenServiceFactory.CreateLanguage('java')open_service.att_cities()print '某公司3开始对接php...'open_service = OpenServiceFactory.CreateLanguage('php')open_service.att_cities()print '某公司4开始对接c#...'open_service = OpenServiceFactory.CreateLanguage('c#')open_service.att_cities()

运行:

➜  static_factory python static_factory.py

某公司1开始对接python...

攻城师 苦逼兮兮, 写python

某公司2开始对接java...

攻城师 苦逼兮兮, 写java

某公司3开始对接php...

攻城师 屌屌的, 写php,毕竟php是世界上最好的语言

某公司4开始对接c#...

攻城师 苦逼兮兮, 写c#

简单工厂思密达

某公司1开始对接python...

攻城师 苦逼兮兮, 写python

某公司2开始对接java...

攻城师 苦逼兮兮, 写java

某公司3开始对接php...

攻城师 屌屌的, 写php,毕竟php是世界上最好的语言

某公司4开始对接c#...

攻城师 苦逼兮兮, 写c#

➜  static_factory

结论: 简单工厂模式并没有消除工厂类的条件判断

    当有需求扩展时候,必须修改工厂类,违背了了本文一开始提出的开放封闭原则

所以,这不是一个完美的模式,于是有人把简单工厂开除出了设计模式。

真是的。其实人家也是有不少优点的。

1. 减少耦合,子类单独实现算法

2. 客户端调用时,只需关心工厂类,减少复杂度

3. 工厂封装和抽象了变化的部分,通过工厂来实现了子类的创建,子类通过多态实现基类方法.

以上,简单工厂模式,希望对您有所帮助。。

to be continued

 

转载于:https://www.cnblogs.com/kakaliush/p/5256175.html

[python实现设计模式]-3.简单工厂模式-触宝开放平台相关推荐

  1. 大牧絮叨设计模式:简单工厂模式

    文章目录 1. 简单工厂模式概述 1.1.简单工厂模式核心组件 1.2.简单工厂模式优缺点 2.` Java`实现 公共父类定义 产品具体实现类 简单工厂定义 代码运行测试: 3. `Python`实 ...

  2. php的类图怎么生成_PHP设计模式之简单工厂模式

    PHP设计模式之简单工厂模式 先从简单工厂入门,不管是面试还是被他人面试,在问到设计模式的时候,大多数人都会提到工厂模式.毫无疑问,工厂相关的几种模式在设计模式中是最出名的也是应用比较广泛的一种模式. ...

  3. C#设计模式(2)——简单工厂模式

    一.引言 这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式--简单工厂模式. 二.简单工厂 ...

  4. 工厂模式 java场景_研磨设计模式之简单工厂模式(场景问题)

    简单工厂不是一个标准的设计模式,但是它实在是太常用了,简单而又神奇,所以还是需要好好掌握的,就当是对学习设计模式的热身运动吧.为了保持一致性,我们尽量按照学习其它模式的步骤来进行学习. 1  场景问题 ...

  5. .NET设计模式(1): 简单工厂模式

    .NET设计模式(1): 简单工厂模式 最近一直在看设计模式,想把自己的学习笔记与大家分享一下,如果能帮助大家的话,我会非常高兴,同时也欢迎大家指出里面的不足.园子里其实关于此类文章已经很多了,如果d ...

  6. JS常用的设计模式(2)——简单工厂模式

    JS常用的设计模式(2)--简单工厂模式 简单工厂模式是由一个方法来决定到底要创建哪个类的实例, 而这些实例经常都拥有相同的接口. 这种模式主要用在所实例化的类型在编译期并不能确定, 而是在执行期决定 ...

  7. 设计模式之简单工厂模式(C#版)

    设计模式之简单工厂模式(C#版) 简介 假设有个女朋友 总结 简介 我用最简洁而直接的方式来描述一下,什么是简单工厂模式.一句话就是,工厂类使用switch case语句返回特定类型. 下面,我们用一 ...

  8. 设计模式之简单工厂模式(Java 实现)

    设计模式之简单工厂模式(Java 实现) 本文首发于http://www.imooc.com/wiki/Designlesson/factory.html 简单工厂模式是平时开发过程中最常见的设计模式 ...

  9. python工厂模式 简书_[Python设计模式] 01 - 简单工厂模式

    设计模式的目的是让代码易维护.易扩展,不能为了模式而模式,因此一个简单的工具脚本是不需要用到任何模式的. 简单工厂模式又叫静态工厂方法模式,工厂模式家族中最简单的一种模式.这个模式的基本工作方式: 通 ...

最新文章

  1. 中南大学c语言程序设计2013年下学期期末考试,2013级计算机专业本科生C语言程序设计期末考试资料.doc...
  2. java 解析 jar_解析java中对jar包进行再次修改
  3. 比较好的处理事情的方法
  4. 最小二乘法(一元)推导
  5. 五天学习MySQL 数据库教程(一)1.2SQL介绍
  6. matlab s函数_matlab结构体 rmfield,arrayfun,structfun,struct2cell,cell2struct
  7. 每日一道shell练习(09)——sed处理
  8. Hadoop 面试,来看这篇就够了
  9. 扔鸡蛋问题具体解释(Egg Dropping Puzzle)
  10. Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
  11. 深入理解GBDT回归算法
  12. 机器人语音---走进优必选
  13. 虚拟机web服务器安装与配置,实验Web服务器的安装与配置.doc
  14. 大龄程序员找工作,为什么这么难?
  15. 会让你变得与众不同的22个技巧
  16. 无法重命名文件夹,错误0x80004005 未指定的错误
  17. 闯荡江湖的必备指南(2)
  18. 破除谷歌浏览器Google Chrome启动时打开hao123,2345等流氓网页
  19. Oracle索引(Index)创建使用
  20. 你真的了解分类模型评估指标都有哪些吗?【附Python代码实现】

热门文章

  1. org.apache.poi.POIXMLException: java.lang.reflect.InvocationTargetException
  2. layUI日期格式转换
  3. 【NOIP初赛】【Luogu1787】普及组2013(洛谷初赛题提交水AC方法了解一下)
  4. SQL Server高级查询之常见数据库对象(触发器)第五章节
  5. 教职工使用计算机管理制度,教师配置笔记本电脑管理办法
  6. Fisher算法+两类问题
  7. [蓝桥杯]试题 基础练习 高精度加法
  8. C++11新特性 右值引用与移动语义
  9. OpenGL基础9:纹理
  10. Mysql触发器与动态完整性