上一篇文章我们说到DiagramFactory和其SvgDiagramFactory子类以及它们使用到的类比如(Diagram,SvgDiagram等等),能够很好的实现预订的功能并且也符合抽象工厂的设计模式。

然而,我们的实现并非是非常完美的,至少还有以下几点不足:

1)我们并不需要保存每个工厂的状态,因此,在向create_diagram传递参数的时候,就没有必要传递工厂的实例。

2)SvgDiagramFactory的代码几乎和DiagramFactory完全一样,唯一的区别就在于其返回值在Text或Rectangle的前面加了Svg的前缀,即:SvgText SvgRectangle等等。

3)我们的顶层命名空间中保存了所有的类:DiagramFactory、Digram、Rectangle、TeXT以及所有的SVG相关的类。然而,实际上我们真正需要从外部调用的仅有两个工厂类而已。

4)为了避免类名称的冲突,我们不得不在子类的名称前面添加SVG前缀,实际而言,这样的代码看起来不是很整洁。(解决类名称冲突的另一个解决办法是:把每个类放到自己的模块内部,但是这样做却依然解决不了代码重复的问题)。

本文就着力解决上述四点问题。

我们所要做的第一个改变就是将Diagram,Rectangle及Text类封装进DiagramFactory类中。这就意味着只能用类似于DiagramFactory.Diagram的形式访问这些类。但是,现在我们就就可以为这些类起相同的名字了,因为类名冲突将不复存在,比如SvgDiagramFactory.Diagram。我们也把类所依赖的一些常量封装进了内部,所有,在本模块的内部顶级名称只有:main(), create_diagram(), DiagramFactory和SvgDiagramFactory。

class DiagramFactory:
@classmethod

def make_diagram(Class, width, height):
return Class.Diagram(width, height)
@classmethod

def make_rectangle(Class, x, y, width, height, fill="white",
stroke="black"):

return Class.Rectangle(x, y, width, height, fill, stroke)
@classmethod
def make_text(Class, x, y, text, fontsize=12):
return Class.Text(x, y, text, fontsize)
...

这是我们的新的DiagramFactory类。其中的make_...()方法全部都是类方法。这也就意味着。当被调用时,类将作为第一个参数传递给该函数(就像self被传递给普通类方法一样)。所以,在这种情况下调用DiagramFactory.make_text()就意味着DiagramFactory作为class参数被传递进去,从而一个DiagramFactory.Text对象被创建并返回。

这个改变也意味着,作为派生自DiagramFactory的SvgDiagramFactory类,不再需要自己实现make_...()的函数。比如说,当我们调用SvgDiagramFactory.make_rectangle()这个方法,由于SvgDiagramFactory里并没有该方法,因此就会调用其基类的DiagramFactoy.make_rectangle()方法,但是传进去的class参数确是SvgDiagramFactory.因此,就导致SvgDiagramFactory.Rectangle对象创建并返回。

def main(): ... txtDiagram = create_diagram(DiagramFactory)txtDiagram.save(textFilename)svgDiagram = create_diagram(SvgDiagramFactory)svgDiagram.save(svgFilename)

这些改变也意味着我们可以简化main()函数的设计,因为我们无需再创建factory工厂的实例了。

其余的代码基本和之前一样。比较明显的区别就在于因为我们将常量和非工厂类都封装进工厂的类代码里,我们现在必须使用工厂名称来访问它们。

class SvgDiagramFactory(DiagramFactory):
...
class Text:
def __init__(self, x, y, text, fontsize):
x *= SvgDiagramFactory.SVG_SCALE

y *= SvgDiagramFactory.SVG_SCALE
fontsize *= SvgDiagramFactory.SVG_SCALE // 10

self.svg = SvgDiagramFactory.SVG_TEXT.format(**locals())

这是封装进SvgDiagramFactory类的代码里的Text类,演示了封装的常量是如何被访问的。

好了,这就是抽象工厂代码的的进一步优化,后面我们还会涉足其他设计模式,敬请期待!

转载于:https://blog.51cto.com/13466841/2128773

Python面向对象程序设计之抽象工厂模式之二-一个更加pythonic的抽象工厂相关推荐

  1. python 面向对象程序设计 1.2 编写程序,定义一个Circle类,根据圆的半径求周长和面积。

    题目: 编写程序,定义一个Circle类,根据圆的半径求周长和面积.再由Circle类创建两个圆对象,其半径分别为5和10,要求输出各自的周长和面积. 代码: from cmath import pi ...

  2. 抽象工厂模式 java实例 tclhaier_Unity常用的设计模式_工厂模式系列之抽象工厂模式...

    在工厂方法模式中,工厂只负责生产具体的产品,每一个具体的工厂对应着一个具体的产品,工厂方法也具有唯一性,如果有时候我们需要一个工厂方法提供多个产品而不是一个单一的产品,例如:海尔品牌不止生产海尔TV, ...

  3. python面向对象程序设计实训学生自我总结_Python面向对象程序设计示例小结

    本文实例讲述了Python面向对象程序设计.分享给大家供大家参考,具体如下: 示例1: #encoding:utf-8 '''example 1 class test: def __init__(se ...

  4. python核心编程:Python面向对象程序设计中类的定义、实例化、封装及私有变量/方法详解

    这篇文章主要介绍了Python面向对象程序设计中类的定义.实例化.封装及私有变量/方法,结合具体实例形式较为详细的分析了Python面向对象程序设计中类的定义.实例化.封装.私有变量.私有方法等相关使 ...

  5. python面向对象程序设计实践(初级)——以《三国演义》中三英大战吕布为例

    python面向对象程序设计实践(初级) --以<三国演义>中三英大战吕布为例 设计实现思路: 定义武器类:武器名,攻击力 定义人物类:继承武器类,姓名,生命值 延时函数:延时0.5秒 实 ...

  6. python面向对象程序设计实践(高级)——以《三国演义》中三英大战吕布为例

    python面向对象程序设计实践(初级) --以<三国演义>中三英大战吕布为例 设计实现思路: 设计类 定义武器类:武器名,攻击力 定义人物类:继承武器类,姓名,生命值 设计函数简化对象的 ...

  7. 工厂三兄弟之简单工厂模式(二)

    2 简单工厂模式概述 简单工厂模式并不属于GoF 23个经典设计模式,但通常将它作为学习其他工厂模式的基础,它的设计思想很简单,其基本流程如下: 首先将需要创建的各种不同对象(例如各种不同的Chart ...

  8. Java 设计模式之工厂模式(二)

    原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...

  9. java中的工厂模式_深入理解Java的三种工厂模式

    一.简单工厂模式 简单工厂的定义:提供一个创建对象实例的功能,而无须关心其具体实现.被创建实例的类型可以是接口.抽象类,也可以是具体的类 实现汽车接口 奔驰类 宝马类 简单工厂,既能生产宝马又能生产奔 ...

最新文章

  1. 一个老工程师对理工科学生的忠告
  2. R语言row.names函数为dataframe、matrix设置行名称实战
  3. python与MySQL交互
  4. list替换某一项需要遍历比对再set到对应的position
  5. mysql 事务 隔离级别_MySQL的四种事务隔离级别
  6. 软件工程网络15个人阅读作业1
  7. TCP/IP review之 静态路由
  8. bzoj 3383: [Usaco2004 Open]Cave Cows 4 洞穴里的牛之四(set+BFS)
  9. FFmpeg结构体分析: AVCodecContext编解码器上下文
  10. Linux电脑怎么接投影,linux如何连接投影机
  11. freenom域名申请教程
  12. mysql blob 读取 图片_mysql中以blob形式存储的图片文件 通过ajax方式传输 在js中设置成img控件的src...
  13. 通过QI协议发射和接收的无线充需要做CE认证吗?RED指令?
  14. 简单常用的http压测工具
  15. 如何成为一名合格的学者---从写好一篇学术论文谈起 ---孟德宇
  16. Docker搭建公司内部私有云平台 -- Gitlab
  17. 开机提示ntldr is missing ,系统文件丢失,三种方法修复
  18. mac抓包工具Charles使用详细教程(图文)
  19. 6.6 Mask RCNN
  20. 《数字电子技术课程设计》课程笔记(五)————调试总结

热门文章

  1. ActiveX中添加对话框并显示
  2. JBOSS优化--比较有用的生产环境配置
  3. 多用户虚拟Web3D环境Deep MatrixIP9 1.04发布
  4. WMframework成长日记(一)——框架介绍
  5. Google 发布浏览器3D插件 O3D API
  6. 【python初识】数据和对象
  7. 旋转矩阵、欧拉角、四元数、轴/角之间的转换
  8. intellij tomcat配置
  9. 2016 年 3 月 TIOBE 编程语言排行榜
  10. 关于类中的引用、常量、静态常量的初始化