• 第二十二天


    单例模式

    """
    单例模式:当希望一个类只有一个实例存在的时候,会使用单例模式。
    应用场景:数据库连接。
    数据库:有用户名,有密码:如果都使用的是相同的用户名和相同密码,
    那么进入的就是同一个数据库,产生数据库连接对象
    数据库连接之后,可以对数据库中的表进行操作
    """
    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类
    """
  • 相关阅读:
    chrome安装HostAdmin app
    Python编码问题
    Elasticsearch利用scroll查询获取所有数据
    oracle不小心更新了数据库中的所有内容后的恢复
    git误提交了项目文件和配置文件的恢复方法
    生成banner的网站
    去除字符串中的emoji字符
    爬虫从网页中去取的数据中包含 空格
    高版本的jdk编译过的项目移到低版本的JDK的eclipse中出错的问题
    java爬虫爬取的html内容中空格( )变为问号“?”的解决方法
  • 原文地址:https://www.cnblogs.com/ztx695911088/p/9484258.html
Copyright © 2020-2023  润新知