第四十篇 Python之设计模式总结-简单工厂、工厂方法、抽象工厂、单例模式
一. 简单工厂
简单工厂模式(Simple Factory Pattern):是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类.
简单工厂的用处不大,主要就是一个if...else语句
结合一个具体的例子,把上面的图再对应一下
# 1. 定义一个工厂,对应图中的接受参数
class BigCat(object):
# 接受参数(接受原材料)
def __init__(self, money):
self.money = money
# 工厂基本的生产模板
def pay(self):
print("收到大猫金融支付金额{0}".format(self.money)) # 2. 定义不同的产品生产线
class WeChat(object): def __init__(self, money):
self.money = money def pay(self):
print("收到微信支付金额{0}".format(self.money)) class ZhiFuBao(object): def __init__(self, money):
self.money = money def pay(self):
print("收到支付宝支付金额{0}".format(self.money)) # 3. 输入参数(原材料入场)
channel = input("请选择支付方式:")
money = input("请输入消费金额:") # 简单工厂,if...else判断就行了
# 4. 根据接收的不同原材料,判断是生产什么产品的,然后进行对应产品线的具体生产
# 如果是要微信支付
if channel == 'WeChat':
WeChat(money).pay() # Wechat()实例化,生产微信对应的产品
elif channel == 'ZhiFuBao':
ZhiFuBao(money).pay()
else:
BigCat(money).pay()
class Fruit:
def __init__(self,name,weight):
self.name = name
self.weight = weight def product(self):
print("这是{},重量是{}吨,用来生产混合果汁的".format(self.name, self.weight)) class Apple(Fruit):
def __init__(self,name,weight):
super(Apple, self).__init__(name,weight) def product(self):
print("这是{},重量是{}吨,用来生产{}罐头的".format(self.name, self.weight, self.name)) class Peer(Fruit):
def __init__(self,name,weight):
super(Peer, self).__init__(name, weight) def product(self):
print("这是{},重量是{}吨,用来生产{}罐头的".format(self.name, self.weight, self.name)) if __name__ == "__main__":
name = input("请输入原材料:")
weight = input("请输入原材料的重量: ")
if name == 'Apple':
Apple(name, weight).product()
elif name == "Peer":
Peer(name, weight).product()
else:
Fruit(name, weight).product()
实现简单水果工厂,可以根据水果名生产对应的水果罐头
二.工厂方法
工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延时到其子类.
工厂方法模式克服了简单工厂模式违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点
场景:雷锋工厂,不关心执行者,只关心执行结果
工厂方法的实现要点:
1. 先要定义每一个产品的具体生产细节(定义每一个产品的类)
2. 再给需要的每一个产品都创建一个生产工厂,提供一个统一的创建方法,然后该创建方法返回具体的产品
3. 这个过程就是把每个产品的生产细节在工厂方法里给包装了一个,外部使用者调用的时候是看不到具体的实现细节的。 工厂方法的使用:
1. 要使用哪个工厂方法,就from...import...,导入具体的工厂方法
2. 然后调用该工厂,获取具体的产品(方法)
3. 有了具体的产品(方法)就可以执行具体的逻辑了 工厂方法传参数会有个小的注意点需要小心,有两种处理方式可以灵活使用:
1. 在定义每个产品类的时候不要在构造方法里接受参数,直接在具体的类方法里接受参数,对应的也使用的时候,也只在调用具体的方法的时候传参
2. 在每个产品类的构造方法里传参, 工厂方法与简单工厂的比较:
1. 不需要給使用者暴露具体的产品的生产过程细节,能封装很多细节,只给使用者提供了一个接口,更解耦;而简单工厂则都暴露给了使用者
2. 如果有新增,简单工厂就需要添加一个if;而工厂方法虽然也需要添加,但是使用者需要使用的时候只需要import对应的工厂方法就可以了,不用的话就无所谓了
3. 工厂方法最大的优点就是把对象的获取和对象的创建给隔离开了,根本不关心对象是怎么创建的 举例:
有个大猫金融、支付宝、微信三种支付渠道,实现一个工厂方法并使用工厂方法
1. 实现工厂方法,文件名:factorymethodpractice.py
# 1. 先定义不同的支付方式(对应工厂里具体的产品),及每个产品具体的生产细节 class BigCat():
# 关于传参的处理方式一: 有构造函数
def __init__(self,money):
self.money = money def pay(self):
print("收到大猫金融的支付金额{0}".format(self.money)) class WeChat():
# 关于传参的处理方式二:直接就没有构造函数,只在具体的方法里接受参数
def pay(self, money):
print("收到微信支付的金额{0}".format(money)) class ZhiFuBao():
def __init__(self, money):
self.money = money def pay(self):
print("收到支付宝支付的金额{0}".format(self.money)) # 2. 为每个支付方式(每个产品)定义特定的工厂,每个工厂都有具体的工厂方法函数,负责返回
# 具体的工厂方法函数,其实就是对每个产品具体的生产细节进行了包装,让外部使用者只能用,却不知道具体的生产过程细节 # 3. 对外只提供这些特定的工厂(接口)
class BigCatFactory():
# 关于传参的处理方式一:
# 因为BigCat()类是需要传参的,return其实就是先调用BigCat()类,将BigCat()执行结果返回,所以也需要传参
# 因此,可以在create的时候就传递参数
def create(self,money):
return BigCat(money) class WeChatFactory():
# 关于传参的处理方式二:
# WeChat()没有构造函数,初始化的时候不接收参数,所以对外提供的接口不需要传参
# 只有在调用WeChat下面具体的pay()方法时才需要传递参数
def create(self):
return WeChat() class ZhiFuBaoFactory():
def create(self, money):
return ZhiFuBao(money)
2. 使用工厂方法: usefactorymethod.py
# 1. 先获取工厂
from factorymethodpractice import BigCatFactory # 获取工厂
factory = BigCatFactory() # 2. 调工厂去创建具体的产品
# 关于传参的处理方式一:在调用create的时候就给create传递参数
payment = factory.create(100) # # 3. 有了具体的产品,就可以去执行具体产品里具体的逻辑了
payment.pay() ''' ------------------------- ''' from factorymethodpractice import WeChatFactory
factory = WeChatFactory()
payment = factory.create()
# 关于传参的处理方式二:只在调用具体方法的时候给需要传参的方法才传递参数
payment.pay(200)
再举个例子说明工厂方法及两种参数不同的处理方式
# 接口文件 fruitfactorypractice.py # 定义Apple产品类,实现具体的生产细节
class Apple():
# 参数处理方式一:有构造方法
def __init__(self,name):
self.name = name def appleguantou(self):
print("{}罐头生产出来了".format(self.name)) # 定义生产Apple的工厂方法
class AppleFactory():
# create的时候就需要传递参数,因为Apple在实例化的时候就需要用到参数
def create(self, name):
return Apple(name) ### ++++++++++++++++++++++++++### # 定义Pear产品类,实现具体的生产细节
class Pear(object):
# 参数的处理方式二:没有构造方法
def pearguantou(self,name):
print("{}罐头生产出来了".format(name))
# 定义生产Pear的工厂方法
class PearFactory(object):
# 参数的处理方式二:create的时候不需要传递参数,只有在调用到需要用参数的方法pearguantou的时候才传递参数
def create(self):
return Pear()
# 调用文件,使用工厂方法 文件名:usefactorymethod.py from fruitfactorypractice import AppleFactory
factory = AppleFactory()
proment = factory.create('第四十篇 Python之设计模式总结-简单工厂、工厂方法、抽象工厂、单例模式的更多相关文章
- 孤荷凌寒自学python第四十天python 的线程锁RLock
孤荷凌寒自学python第四十天python的线程锁RLock (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 因为研究同时在多线程中读写同一个文本文件引发冲突,所以使用Lock锁尝试同步, ...
- 设计模式之工厂模式VS抽象工厂
一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...
- 详解设计模式之工厂模式(简单工厂+工厂方法+抽象工厂) v阅读目录
1楼留头头大神:http://www.cnblogs.com/toutou/p/4899388.html v阅读目录 v写在前面 v简单工厂模式 v工厂方法模式 v抽象工厂模式 v博客总结 v博客 ...
- C# 设计模式(1)——简单工厂模式、工厂模式、抽象工厂模式
1.前言 上一篇写了设计模式原则有助于我们开发程序的时候能写出高质量的代码(牵一发而不动全身),这个系列还是做个笔记温习一下各种设计模式,下面就看看简单工厂模式.工厂模式.抽象工厂模式. 2.简单工厂 ...
- Delphi 设计模式:《HeadFirst设计模式》Delphi代码---工厂模式之抽象工厂[转]
1 2 {<HeadFirst设计模式>工厂模式之抽象工厂 } 3 { 抽象工厂的产品 } 4 { 编译工具:Delphi7.0 ...
- [python实现设计模式]-3.简单工厂模式-触宝开放平台
预备知识: 开放封闭原则(Open-Closed Principle OCP) Software entities(classes,modules,functions etc) should open ...
- 大话设计模式C++实现-第15章-抽象工厂模式
一.UML图 二.概念 抽象方法模式(Abstract Factory):提供一个创建一系列相关或互相依赖对象的接口,而无需指定他们详细的类. 三.包括的角色 (1)抽象工厂 (2)详细工厂:包含详细 ...
- Java设计模式从精通到入门五 抽象工厂方法模式
定义 抽象工厂类为创建一组相关和相互依赖的对象提供一组接口,而无需指定一个具体的类. 这里我得把工厂方法模式得定义拿出来做一下比较:定义一个创建对象的接口,由子类决定实例化哪一个类.工厂方法是一个 ...
- C#设计模式——简单工厂模式、工厂模式和抽象工厂模式
一:简单工厂模式 1:描述:简单工厂模式是由一个工厂对象根据接收到的消息决定要创建哪一个类的对象事例. 2:优点:工厂类中有相关逻辑判断,可以根据需要动态创建相关的对象事例,而客户端只需要告诉工厂类创 ...
随机推荐
- PAT——1045. 快速排序
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边. 给定划分后的N个互不相同的正整数的排列,请问有多 ...
- Xcode4.4(LLVM4.0编译器)中NSArray, NSDictionary, NSNumber优化写法
Xcode4.4(LLVM4.0编译器)中NSArray, NSDictionary, NSNumber优化写法 从xcode4.4开始,LLVM4.0编译器为Objective-C添加一些新的特性. ...
- Office365学习笔记—获取当前用户
1,页面上有个_spPageContextInfo对象,可以获取一些我们需要的东西. (1)获取当前用户Id var userId=_spPageContextInfo.userId; (2)获取当前 ...
- Java编码问题原因以及解决
一.文件编码 Unicode 是首选编码.Unicode 是全球范围的字符编码标准. 小结: GBK 与unicode之间的转换是通过gbk unicode映射表. UTF-8 与unicode之间的 ...
- 【转载】决策树Decision Tree学习
本文转自:http://www.cnblogs.com/v-July-v/archive/2012/05/17/2539023.html 最近在研究规则引擎,需要学习决策树.决策表等算法.发现篇好文对 ...
- Jquery中on绑定事件 点击一次 执行多次 的解决办法
举个例子,在同一个页面有下拉选择框 <select class="mySelect"> <option value="user">按用户 ...
- E. K Balanced Teams
类比背包问题,为每个学生附加一个权重$pos[i]$,意思是选择该学生后,之后可以选择$p[i]~p[i]+5$的学生. 转换公式: $$d[i][j]=max(d[i+1][q],d[i+pos][ ...
- kali linux 安装 Mysql Can't read from messagefile 报错解决方案
1.下载安装包 下载地点:https://dev.mysql.com/downloads/mysql/ 或者 wget http://dev.mysql.com/get/Downloads/MySQL ...
- 使用apt-get install时如何指定安装版本
命令语法如下: sudo apt-get install package=version 例如: sudo apt-get install samba=2:4.4.5+dfsg-2ubuntu6
- 支付宝H5、APP支付服务端的区别(php)
php支付宝H5和APP支付1.准备工作需要前往 蚂蚁金服开放平台申请https://openhome.alipay.com/developmentDocument.htm 2.大致流程1.用户添加商 ...