单例模式
"""
单例模式:当希望一个类只有一个实例存在的时候,会使用单例模式。
应用场景:数据库连接。
数据库:有用户名,有密码:如果都使用的是相同的用户名和相同密码,
那么进入的就是同一个数据库,产生数据库连接对象
数据库连接之后,可以对数据库中的表进行操作
"""
class Connection:
pass
p1=Connection()
p2=Connection()
print(p1 is p2)
# 大概的思路:当创建对象的时候,先判断一下,对象是否已存在,
# 如果已存在则返回当前对象即可,如果不存在就创建一个新的对象。
# 在pythonn中实现单例模式方法:
"""
1. 使用模块
2. 使用__new__
3. 使用装饰器
4. 使用元类
"""
1. 使用模块:python本身纯天然就是单例模式。这是python独有。
# 当使用import或者是from都会执行模块中的代码,但是只执行一次
# 在当前的py文件中使用的my永远只有一个。
# from day22.another import my
# my.foo()
2. 使用__new__
# __new__是用来创建对象的。
class MySingleton: _instance=None def __init__(self,x): self.x=x def __new__(cls,*args,**kwargs): # 判断是否应存在对象了 if not cls._instance: # 创建新的对象 print("创建一个新的对象") cls._instance=super().__new__(cls,*args,**kwargs) else: print("没有创建新的对象") return cls._instance one=MySingleton(1) # 先执行new,再执行init two=MySingleton(2) # two=one print(id(one),id(two)) print(one is two) print(one.x) print(two.x)
3.使用装饰器
定义一个装饰器,里面只返回单独的一个对象,在需要使用单例模式创建的类上面加装饰器。
# on_duty=check_in(on_duty)
# @check_in
# class A:
# pass
# A()
# A=check_in(A)
# A()
# 只要去把装饰器函数中的inner方法里,实现创建同一个对象的功能。
from functools import wraps def singleton(cls): _instance={} # 类名:对象 @wraps(cls) def inner(*args,**kwargs): if cls not in _instance: _instance[cls]=cls(*args,**kwargs) print("instance的值",_instance) return _instance[cls] return inner
@singleton #A=singleton(A)
class A:
pass
a1=A()
a2=A()
@singleton #B=singleton(B)
class B:
pass
b=B()
print(A.__name__)
print(a1 is a2)
print(id(a1),id(a2))
4. 使用元类
创建类的类是元类,在元类中有__call__
# a=A()
# a()
# print(type(a))
class Singleton(type): _instance={} def __call__(cls, *args, **kwargs): if cls not in cls._instance: cls._instance[cls]=super().__call__(*args, **kwargs) return cls._instance[cls]
class A(metaclass=Singleton):
pass
a1=A()
a2=A()
print(a1 is a2)
print(id(a1),id(a2))
# 适用性:1.当资源共享的情况下,希望创建的对象只有一个,避免资源的浪费。数据库连接。
# 2.线程池
适配器、桥接、装饰、组合(mix_in)
"""
结构型模式:类和类之间的关系
适配器、桥接、装饰、组合(mix_in)
"""
1. 适配器:当已有的功能可以使用,但是接口和调用者不匹配,需要用适配器。
# 中国球员:前锋、中锋、后卫
# 目标:需要进行是配的对象(外籍中锋)
# 适配器:需要要是配的对象转换成可以使用的类(方式)
class Player:
def attack(self):
pass
def defense(self):
pass
class Forward(Player):
def __init__(self, name):
self.name = name
def attack(self):
print("前锋{}在进攻".format(self.name))
def defense(self):
print("前锋{}在防御".format(self.name))
class Center(Player):
def __init__(self, name):
self.name = name
def attack(self):
print("中锋{}在进攻".format(self.name))
def defense(self):
print("中锋{}在防御".format(self.name))
# 需要被适配的类
class ForginCenter:
def __init__(self, name):
self.name = name
def forginAttack(self):
print("外籍中锋{}在进攻".format(self.name))
def forgindefense(self):
print("外籍中锋{}在防御".format(self.name))
class Guards(Player):
def __init__(self, name):
self.name = name
def attack(self):
print("后卫{}在进攻".format(self.name))
def defense(self):
print("后卫{}在防御".format(self.name))
# 需要一个适配器,希望下面调用ForginCenter的时候,也希望使用attack、defense
class Translator(Player): def __init__(self, name): self.name = name self.forginCenter = ForginCenter(self.name) def attack(self): self.forginCenter.forginAttack() def defense(self): self.forginCenter.forgindefense()
f = Forward("孙悦")
# c=Center("张飞")
c = Translator("奥尼尔")
g = Guards("巩振")
f.attack()
f.defense()
c.attack()
c.defense()
g.attack()
g.defense()
# 使用场景
# 希望使用一个已经存在的类,而它的接口(方法),不符合我们的需求。
# 希望复用一些现存存类,方式跟已有的也不同。
"""
桥接模式:把抽象化和实现化解耦,使得二者独立。接口模式
当使用继承解决问题时,需要创建大量的子类。
"""
# N品牌的手机运行游戏
# class Handsetgame:
# def run(self):
# pass
# class HandsetNgame(Handsetgame):
# def run(self):
# print("正在运行N品牌的手机游戏")
#
# class HandsetMgame(Handsetgame):
# def run(self):
# print("正在运行M品牌的手机游戏")
# ng=HandsetNgame()
# mg=HandsetMgame()
# ng.run()
# mg.run()
# 继续加需求,手机还有通讯录的功能
# class Phone:
# pass
# class MPhone(Phone):
# pass
# class NPhone(Phone):
# pass
# # class Handsetgame:
# # def run(self):
# # pass
# class HandsetNgame(NPhone):
# def run(self):
# print("正在运行N品牌的手机游戏")
#
# class HandsetMgame(MPhone):
# def run(self):
# print("正在运行M品牌的手机游戏")
#
#
# class PhoneNaddress(NPhone):
# def insert(self):
# print("N手机添加通讯录")
# def delete(self):
# print("N手机删除通讯录")
#
#
# class PhoneMaddress(MPhone):
# def insert(self):
# print("M手机添加通讯录")
# def delete(self):
# print("M手机删除通讯录")
#
# ng=HandsetNgame()
# mg=HandsetMgame()
# ng.run()
# mg.run()
#
# na=PhoneNaddress()
# na.insert()
# na.delete()
# 如果再增加功能,需要继承非常多的子类。需要使用到桥接模式。
# 手机---类 游戏、通讯录、MP3(软件)---类
class Soft:
pass
class Address(Soft):
def run(self):
print("运行通讯录")
class Game(Soft):
def run(self):
print("正在运行游戏")
class Mp3(Soft):
def run(self):
print("MP3正在运行")
class Phone: def __init__(self): self.name = None def setSoft(self, soft): self.soft = soft def run(self): print(self.name + "正在", end="") self.soft.run()
class Mphone(Phone):
def __init__(self):
super().__init__()
self.name = "M手机"
class Nphone(Phone):
def __init__(self):
super().__init__()
self.name = "N手机"
class Sphone(Phone):
def __init__(self):
super().__init__()
self.name = "S手机"
mp = Mphone()
a = Address()
mp.setSoft(a)
mp.run()
mp.setSoft(Game())
mp.run()
np = Nphone()
np.setSoft(Address())
np.run()
np.setSoft(Game())
np.run()
# 加MP3功能
np.setSoft(Mp3())
np.run()
# 多一款手机S
sp = Sphone()
sp.setSoft(Mp3())
sp.run()
桥接模式:两个类之间 ,存在一定的依赖关系,但是两个类增加子类非常灵活,非常多。
装饰模式:想一个现有对象上添加功能,而且按照添加功能的顺序执行,又不改变原对象的结构。
# 小明穿衣服
# class People:
# def __init__(self,name):
# self.name=name
# class AbstractCloth:
# def show(self):
# pass
# class Underwear(AbstractCloth):
# def show(self):
# print("[背心]")
# class Tshirt(AbstractCloth):
# def show(self):
# print("[衬衫]")
# class Sweater(AbstractCloth):
# def show(self):
# print("[毛衣]")
# p=People("小明")
# print("小明穿着:")
# sw=Sweater()
# sw.show()
# underwear=Underwear()
# underwear.show()
# tshirt=Tshirt()
# tshirt.show()
# 使用装饰模式实现
# 被装饰的类
class People: def __init__(self, name): self.name = name def show(self): return "{}穿着:".format(self.name) class Decorator: def __init__(self, people): self.people = people class AbstractCloth(Decorator): pass class Underwear(AbstractCloth): def show(self): return self.people.show() + "[背心]" class Tshirt(AbstractCloth): def show(self): return self.people.show() + "[衬衫]"
p = People("张三")
underwearp = Underwear(p)
tshirtP = Tshirt(underwearp)
print(tshirtP.show())
"""
优点:装饰器类和被装饰的类可以独立发展,扩展原有的类的时候,不需要修改原来类的内容
缺点:多层装饰器比较复杂
适用:动态的增加功能。对类进行动态的扩展
"""
"""
mix_in Mixin: 组合模式的特例,整体部分模式。 把一些主体部分跟附加的部分整合起来。
"""
# 茶、牛奶,加糖的牛奶。
# 多继承
class Drink:
pass
class Milk(Drink):
def __init__(self):
self.name = "牛奶"
self.price = 5
# 附属品是mix_in
# 使用mix_in模式的时候,附属品一定是不能单独被实例化。一定没有init方法
class MininSuger:
def addName(self):
return "_糖"
def addPrice(self):
return 2
class MixinSalt:
def addSaltName(self):
return "_盐"
def addSaltPrice(self):
return -1
# 采用多继承实现min_in模式,注意,主体放在前面,
# 附属品放在后面,为了简洁,名字尽量不要重复
class MilkSuger(Milk, MininSuger, MixinSalt):
def get_name(self):
return self.name + self.addName() + self.addSaltName()
def get_price(self):
return self.price + self.addPrice() + self.addSaltPrice()
ms = MilkSuger()
print(ms.get_name())
print(ms.get_price())
"""
适用性:
1. 需要表名整体-部分结构,一个是主体,N个附属品,附属品是mix_in
2. 对于主体部分可以单独创建, 对于附属品,业务上不可以单独创建。
优点:客户端调用方便
缺点:最终的mix_in都是实现类,都不是接口,会违反依赖倒置原则。
注意:
1. 是python这种多继承的语言才有的模式
2. mix_in不定义init方法
3. mix_in尽量精简
4.关系上,子类即使没有继承mix_in,也可以单独存在(主体部分可以独立存在)
mix_in没有主体,不能被执行
5. 继承的顺序尽量让mix_in放在后面,同时还要尽量避免同名函数。
6. 只有一个主体类,其他都是mix_in
7. mixin不能继承非mixin类
"""