一.简单工厂
下面是简单工厂的UML图
解释:
有个CreateA类,它可以创建一个A类,这个A类可以是A1 ,也可以是A2,然后执行do方法
简单工厂:你选择什么样的模式,就生成什么产品
简单工厂模式(Simple Factory Pattern):是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类.
简单工厂的用处不大,主要就是一个if...else语句,写死的硬编码,想加功能必须改代码
示例1
# 根据不同的支付渠道选择对应的支付方式 class Pay(): def __init__(self,money): self.money = money def pay(self): print("京东金融支付{}元".format(self.money)) class ZhiFuBao(): def __init__(self, money): self.money = money def pay(self): print("支付宝支付{}元".format(self.money)) class WeChat(): def __init__(self, money): self.money = money def pay(self): print("微信支付{}元".format(self.money)) channel = input("请输入支付方式:") money = input("请输入支付金额:") if channel == 'WeChat': WeChat(money).pay() elif channel == 'ZhiFuBao': ZhiFuBao(money).pay() else: Pay(money).pay()
示例2:实现简单工厂,可以根据水果名生产对应的水果
class Fruit(object): def __init__(self,name,price): self.name = name self.price = price class Apple(Fruit): def __init__(self,name,price): super(Apple,self).__init__(name,price) print("apple") class Peer(Fruit): def __init__(self,name,price): super(Peer,self).__init__(name,price) print("peer") class Banana(Fruit): def __init__(self,name,price): super(Banana, self).__init__(name,price) print("banana") class Watermelon(Fruit): def __init__(self,name,price): super(Watermelon, self).__init__(name,price) print("西瓜") # 简单工厂 factory = input("请输入要生产的水果:") if factory == "Apple": Apple("红元帅",12) # 实例化 elif factory == "Peer": Peer("雪花梨",2.5) elif factory == "Banana": Banana("小芭蕉",5) elif factory == "Watermelon": Watermelon("小麒麟",1.8)
二. 工厂方法
工厂方法最大的特点: 把对象的获取和对象的创建给隔离开了
1. 定义工厂方法
# 1。 先定义每个产品(方法)的具体生产细节 class JingDongJinRong(): # 传参处理方式一:有构造函数,构造柱函数接受参数了,所以对应到下面的工厂方法里,也需要在create的时候就传参 def __init__(self,money): self.money = money def pay(self): print("收到京东金融支付的{}元".format(self.money)) # 有初始化函数接受参数,此处就是self.money参数 class ZhiFuBao(): # 关于传参的处理方式二:直接就没有构造函数,只在具体的方法里接受参数,所以对应到下面的工厂方法里,也可不传参 def pay(self,money): print("收到支付宝支付的{}元".format(money)) # 无初始化函数接收参数,而是方法直接接受参数,此处直接就是参数名,不加self class WeChat(): def pay(self,money): print("收到微信支付的{}元".format(money)) # 2. 再给每个产品定义一个特定的生产工厂,该生产工厂有具体的工厂方法,负责返回具体的工厂方法函数 class JingDongJinRongFactory(): # 传参处理方式一: # 因为JingDongJinRong()类是需要传参的,return其实就是先调用JingDongJinRong()类,将JingDongJinRong()执行结果返回,所以也需要传参 # 因此,可以在create的时候就传递参数 def create(self,money): return JingDongJinRong(money) class ZhiFuBaoFactory(): # 关于传参的处理方式二: # ZhiFuBao()没有构造函数,初始化的时候不接收参数,所以对外提供的接口不需要传参 # 只有在调用ZhiFuBao下面具体的pay()方法时才需要传递参数 def create(self): return ZhiFuBao() class WeChatFactory(): def create(self): return WeChat()
2. 使用工厂方法
# 使用京东金融支付工厂方法前,需要先导入工厂方法里的对应工厂 from FactoryMethodDefined import JingDongJinRongFactory jindongjinrongfactory = JingDongJinRongFactory() # 先实例化,类似于获取工厂 # 传参处理方式一:在调用create的时候就给create传递参数 payment_jingdong = jindongjinrongfactory.create(200) # 再调用创造工厂的函数,调工厂去创建具体的产品 payment_jingdong.pay() # 有了具体的产品,就可以执行具体产品里具体的生产逻辑了 # 使用支付宝工厂方法前,先导入支付宝工厂 from FactoryMethodDefined import ZhiFuBaoFactory zhifubaofactory = ZhiFuBaoFactory() payment_zhifubao = zhifubaofactory.create() # 传参处理方式二:只在调用具体方法的时候给需要传参的方法才传递参数 payment_zhifubao.pay(100) from FactoryMethodDefined import WeChatFactory wechatfactory = WeChatFactory() payment_wechat = wechatfactory.create() payment_wechat.pay(500.99)
示例2:水果工厂
1. 为每个具体产品创建工厂类,每个工厂类里有个创建的方法,返回具体的产品
class Fruit(object): def __init__(self,name,price): self.name = name self.price = price class Apple(Fruit): def __init__(self,name,price): super(Apple,self).__init__(name,price) print("apple") def sweet(self): print("{}一斤的{}真是甜那".format(self.price,self.name)) class Peer(Fruit): def __init__(self,name,price): super(Peer,self).__init__(name,price) print("peer") class Banana(Fruit): def __init__(self,name,price): super(Banana, self).__init__(name,price) print("banana") class Watermelon(Fruit): def __init__(self,name,price): super(Watermelon, self).__init__(name,price) print("西瓜") # 定义工厂 class AppleFactory(): # 这是套路,固定写法了 def create(self,name,price): return Apple(name,price) class PeerFactory(): def create(self,name,price): return Apple(name,price) class BananaFactory(): def create(self,name,price): return Apple(name,price) class WatermelonFactory(): def create(self,name,price): return Apple(name,price)
2. 工厂方法的使用
from fruitFactoryDefined import AppleFactory applefactory = AppleFactory() apple = applefactory.create("苹果",12) apple.sweet()
三. 抽象工厂(一定要掌握的设计模式)
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的类
抽象工厂最大的优点是:代码量少了很多,通过反射的方法就可以找出函数,比如在单元测试框架里,抽象方法是大量使用到的。
在抽象工厂就是利用反射机制实现的,反射是非常重要的,会大量使用到
抽象工厂最大的特点:不像工厂方法或者简单工厂那样需要硬编码,抽象工厂知道文件名、类名,通过反射的方式就是搞到方法。
1. 反射
什么是反射?
反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!
上面的概念指出了使用反射需要掌握的知识点:
a.通过字符串的形式,导入模块——>要用到:__import__()
b.通过字符串的形式,去模块寻找指定函数并执行 ——> 用要到:getattr()
c.利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员——>要用到:setattr(),hasattr(),delattr()
了解掌握上面5个函数是反射的前提。
(1) __import__()
作用: __import__()可以实现以字符串的形式动态导入模块的目的
上面通过 from... import... 或者 import ... 最终都会解释成 __import__(),所以,也就可以直接使用 __import__()去导入模块
# 导入一个模块名,其实是.py文件名 model = __import__("FactoryMethodDefined") print(model) # 输出 返回的是模块的路径 <module 'FactoryMethodDefined' from '/Users/qiaoersun/Documents/千万别删/测试/Codes/testfanStudyPractice/lesson4_0623/FactoryMethodDefined.py'> # 查看导入的模块里都有什么 print(dir(model)) # ['JingDongJinRong', 'JingDongJinRongFactory', 'WeChat', 'WeChatFactory', 'ZhiFuBao', 'ZhiFuBaoFactory', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
上面的写法还是不够灵活,有这样一个需求, 需动态输入一个模块名(当然输入的就是字符串了),可以随时访问到导入模块中的方法或者变量,怎么做呢?
就要用到__import__()方法
modelName = input("请输入要导入的模块名:") mod = __import__(modelName) print(mod) # 输出 <module 'FactoryMethodDefined' from '/Users/qiaoersun/Documents/千万别删/测试/Codes/testfanStudyPractice/lesson4_0623/FactoryMethodDefined.py'> print(dir(mod)) # 输出 ['JingDongJinRong', 'JingDongJinRongFactory', 'WeChat', 'WeChatFactory', 'ZhiFuBao', 'ZhiFuBaoFactory', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
(2)getattr()
modelName = input("请输入要导入的模块名:") mod = __import__(modelName) # 上面有了导入,如果想看模块或者文件里有什么内容,怎么获取呢? object = getattr(mod,"ZhiFuBao") print(object) # <class 'FactoryMethodDefined.ZhiFuBao'> 是个类 print(object()) #<FactoryMethodDefined.ZhiFuBao object at 0x1046c7828> 就是个对象了 # 调用方法 object().pay(400) # 收到支付宝支付的400元
但是,这样相当于写死了,还是不够灵活,更灵活的处理如下
modelName = input("请输入要导入的模块名:") class_ = input("请输入类型名:") mod = __import__(modelName) object = getattr(mod,class_) object().pay(400)
(3)hasattr(object, name)
判断对象object是否包含名为name的特性(hasattr是通过调用getattr(ojbect, name)是否抛出异常来实现的)
object:表示对象,可以是类名,也可以是实例名
name: 属性名,是个字符串形式的
class Test(): def __init__(self,price): self.price = price def unitTest(self): print("pass") test = Test(66.66) print(hasattr(test,"price")) # True print(getattr(test,"price")) # 66.66 test.name = "奥迪" print(hasattr(test,"name")) # True print(getattr(test,"name")) # 奥迪 print(hasattr(test,"unitTest")) # True print(hasattr(test,"price2")) # False print(getattr(test,"unitTest")) # <bound method Test.unitTest of <__main__.Test object at 0x10e7de198>>
(4) delattr(object, name)
与setattr()相关的一组函数。参数是由一个对象(记住python中一切皆是对象)和一个字符串组成的。
string参数必须是对象属性名之一。该函数删除该obj的一个由string指定的属性。delattr(x, 'foobar')=del x.foobar
object:表示对象,可以是类名,也可以是实例名
name: 属性名,是个字符串形式的
# 先删除属性 delattr(test, 'name') # 再通过hasattr()查看该属性是否还存在 print(hasattr(test,'name')) # False # 注意: # 这不是真的删除,而是只在内存里操作
(5)setattr(object, name, value)
这是相对应的getattr()。参数是一个对象,一个字符串和一个任意值。字符串可能会列出一个现有的属性或一个新的属性。
这个函数将值赋给属性的。该对象允许它提供。例如,setattr(x,“foobar”,123)相当于x.foobar = 123。
setattr(test,"name","大众") print(test.name) # 大众 print(getattr(test,"name")) #大众
四. 单例模式(用的不多,但是要能背下来)
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保一个类只能有一个实例存在。当你希望在整个系统中,某个类只能创建一个实例时,单例对象就能派上用场。
常见的配置文件,数据库连接等都会用到单例模式
实现单例模式有很多种方法
1. 基于__new__方法实现(推荐使用,方便)---要背下来
原理:当实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object.__new__)实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,因此我们可以基于这个,改造__new__()方法,在__new__里控制他只返回一个对象,从而实现单例模式.
class Singleton(): def __new__(cls, *args, **kwargs): # "_instance" 是变量名,可以随便取 if not hasattr(cls,"_instance"): cls._instance = super(Singleton,cls).__init__(cls) # 上面的写法等价于下面的写法 # cls._instance = object.__init__(cls) return cls._instance # 验证 single1 = Singleton() single2 = Singleton() print(id(single1)) print(id(single2)) # 单例的继承 class Apple(Singleton): def apple(self): pass apple1 = Apple() apple2 = Apple() print(id(apple1)) print(id(apple2)) # 输出 4469315672 4469315672 4469315672 4469315672
2.使用修饰器 实现单例模式---很多面试可能会问,要背下来
基于闭包实现
def Singleton2(cls,*args,**kwargs): instance = {} def get_instance(): if cls not in instance: instance[cls] = cls(*args, **kwargs) return instance[cls] return get_instance @Singleton2 def Apple(): pass apple1 = Apple() apple2 = Apple() print(id(apple1)) print(id(apple2)) # 4522248280 # 4522248280