python常用的设计模式(代码片段)

白水baishui 白水baishui     2022-10-25     662

关键词:

文章目录

1. 设计模式

设计模式是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计。

  • 设计模式的分类
    创建型模式:工厂方法模式、抽象工厂模式、创建者模式、原型模式、单例模式。隐藏底层模块的逻辑,关注怎么创建对象

结构型模式:适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式。类之间如何协同工作,应该组成什么结构

行为型模式:解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模板方法模式。关注行为,也就是方法,应该怎样某些行为

  • 面向对象
    设计模式解决的就是面向对象中的问题。需要指导面向对象的三大特性是 封装、继承和多态 ,封装是把数据和方法封装到类中,继承是类之间复用代码,多态在Python中默认支持的,Python是一种多态的语言。

  • 接口
    接口是若干抽象方法的集合。接口的作用是限制实现接口的类必须按照接口给定的调用方式实现这些方法,对高层模块隐藏了类的内部实现。下面通过一个简单的例子来加强对接口的理解:

from abc import ABCMeta, abstractmethod

# 具有抽象方法的类就是接口类,
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        """
        抽象方法,在实现的类中必须实现的方法。限制实现接口的类必须按照接口给定的调用方式实现这些方法
        :param money: 
        :return: 
        """
        pass

# 不能说是继承接口类,应该说是实现接口
class Alipay(Payment):
    def pay(self, money):
        """
        实现接口类中的必须实现的方法
        :param money:
        :return:
        """
        print("支付宝支付了0元!".format(money))

class WechatPay(Payment):
    def pay(self, money):
        """
        实现接口类中的必须实现的方法
        :param money:
        :return:
        """
        print("微信支付了%d元!" % (money))

# 下面是高层代码,在调用的时候是看不到底层类的内部实现
a = Alipay()
w = WechatPay()
a.pay(100)
w.pay(100)

2. 面向对象设计原则

  • 开放封闭原则
    一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应该在不修改原代码的情况下进行修改。
  • 里氏替换原则
    所有引用父类的地方必须能透明地使用其子类的对象,即能调用父类就一定能调用其子类,一个简单的例子加强理解
class User(object):
    def print_name(self):
        pass

class VipUser(User):
    def print_name(self):
        """
        保证参数和返回值类型需要和父类一样
        :return:
        """
        pass
def print_name(u):
    """
    不论使用User还是继承User的VipUser,调用的方式是一样的。这就要求User和VipUser的方法参数和返回值类型是一样的
    :param u:
    :return:
    """
    u.print_name()
    

# 无论是实现User()还是VipUser()都是可以的
u = User()
# u = VipUser()
print_name(u)
  • 依赖倒置原则
    高层模块不应该依赖底层模块,二者都应该依赖抽象。抽象不应该依赖细节,细节应该应该依赖抽象。要针对接口编程,而不是针对实现变成。通过例子加强理解:
from abc import ABCMeta, abstractmethod

# 接口,抽象不应该依赖细节
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass
        
# 底层代码和高层代码都是细节,细节应该依赖抽象
# 底层代码
class Alipay(Payment):
    def pay(self, money):
        print("支付宝支付了0元!".format(money))

class WechatPay(Payment):
    def pay(self, money):
        print("微信支付了%d元!" % (money))

# 高层代码,高层模块不应该依赖底层模块,二者都应该依赖抽象
a = Alipay()
w = WechatPay()
a.pay(100)
w.pay(100)
  • 接口隔离原则
    使用多个专门的接口,而不使用单一的总结口,高层的代码不应该依赖那些它不需要的接口。通过例子加强理解:
from abc import ABCMeta, abstractmethod

class LandAnimal(metaclass=ABCMeta):
    @abstractmethod
    def walk(self):
        pass

class WaterAnimal(metaclass=ABCMeta):
    @abstractmethod
    def swim(self):
        pass

class SkyAnimal(metaclass=ABCMeta):
    @abstractmethod
    def fly(self):
        pass

# 高层的代码不应该依赖那些它不需要的接口
class Tiger(LandAnimal):
    def walk(self):
        pass

# 高层的代码不应该依赖那些它不需要的接口
class Frog(LandAnimal, WaterAnimal):
    def walk(self):
        pass
  • 单一职责原则
    不要存在多于一个导致类变更的原因,一个类只负责一项职责,一个类只做一件事。把面向过程的代码放到类中,虽然用到了类,但不是面向对象

3. 创建型模式

3.1. 简单工厂模式

简单工厂模式不是23中设计模式中的,但是必须要知道。简单工厂模式不直接向客户端暴露对象创建的细节,而是通过一个工厂类来负责创建产品类的实例。简单工程模式的角色有:工厂角色(工厂类)、抽象产品角色(接口类)、具体产品角色(实现类)。通过例子来加深理解:

from abc import ABCMeta, abstractmethod


# 抽象产品角色,以什么样的表现去使用
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass

# 产品角色
class Alipay(Payment):
    def __init__(self, use_huabei=False):
        self.use_huabei = use_huabei

    def pay(self, money):
        if self.use_huabei == True:
            print("花呗支付了0元!".format(money))
        else:
            print("支付宝余额支付了0元!".format(money))

# 产品角色
class WechatPay(Payment):
    def pay(self, money):
        print("微信支付了%d元!" % (money))

# 工厂类角色
class PaymentFactory:
    def ctreate_payment(self, method):
        if method == 'Alipay':
            return Alipay()
        elif method == 'WechatPay':
            return WechatPay()
        elif method == 'HuabeiPay':
            return Alipay(use_huabei=True)
        else:
            raise TypeError('No such payment named %s' % method)

# 客户端调用。不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例
pf = PaymentFactory()
p = pf.ctreate_payment('HuabeiPay')
p.pay(100)

3.2. 工厂方法模式

简单工厂模式只创建一个工厂类,当有新的产品时,需要修改工厂类代码。而 工厂方法模式的每个具体产品对应一个具体的工厂类,不需要修改工厂类代码,并且同时也能满足隐藏对象创建的细节。但是工厂方法模式也是有缺点的,就是 每增加一个具体产品类,就必须增加一个相应的具体方法
工厂模式方法模式的概念是定义了一个用于创建对象的接口(工厂接口),让子类决定实例化那一个产品类。角色有抽象工厂角色、具体工厂角色、抽象产品角色和具体产品角色。通过例子来加深理解,每个具体产品对应一个具体的工厂类:

from abc import ABCMeta, abstractmethod

# 抽象产品角色
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass

# 具体产品角色
class Alipay(Payment):
    def __init__(self, use_huabei=False):
        self.use_huabei = use_huabei

    def pay(self, money):
        if self.use_huabei == True:
            print("花呗支付了0元!".format(money))
        else:
            print("支付宝余额支付了0元!".format(money))

class WechatPay(Payment):
    def pay(self, money):
        print("微信支付了%d元!" % (money))

# 抽象工厂角色
class PaymentFactory(metaclass=ABCMeta):
    @abstractmethod
    def create_payment(self):
        pass

# 具体工厂角色
class AlipayFactory(PaymentFactory):
    def create_payment(self):
        return Alipay()

class WechatPayFactory(PaymentFactory):
    def create_payment(self):
        return Alipay()

class HuabeiFactory(PaymentFactory):
    def create_payment(self):
        return Alipay(use_huabei=True)

hfp = HuabeiFactory().create_payment()
hfp.pay(100)  # 花呗支付了100元!

缺点是每增加一个具体产品类,就必须增加一个相应的具体方法:

from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass

class Alipay(Payment):
    def __init__(self, use_huabei=False):
        self.use_huabei = use_huabei

    def pay(self, money):
        if self.use_huabei == True:
            print("花呗支付了0元!".format(money))
        else:
            print("支付宝余额支付了0元!".format(money))

class WechatPay(Payment):
    def pay(self, money):
        print("微信支付了%d元!" % (money))

class BankPay(Payment):
    def pay(self, money):
        print("银行支付了%d元!" % (money))

# 创建产品的工厂类的接口
class PaymentFactory(metaclass=ABCMeta):
    @abstractmethod
    def create_payment(self):
        pass

# 工厂类
class AlipayFactory(PaymentFactory):
    def create_payment(self):
        return Alipay()

# 工厂类
class WechatPayPayFactory(PaymentFactory):
    def create_payment(self):
        return Alipay()

# 工厂类
class HuabeiPayFactory(PaymentFactory):
    def create_payment(self):
        return Alipay(use_huabei=True)

# 新增加银行支付的工厂类
class BankPayFactory(PaymentFactory):
    def create_payment(self):
        return BankPay()

bfp = BankPayFactory().create_payment()
bfp.pay(100)  # 银行支付了100元!

3.3. 抽象工厂模式

抽象工厂模式:定义一个工厂类的接口让工厂子类来创建一系列相关或者相互依赖的对象。相比工厂方法模式,抽象工厂模式中的每一个具体工厂都生产一套产品。下面是生产厂商生产一部手机的例子:生产一部手机如果说只需要手机壳、CPU和操作系统这三个类对象,其中每个类对象都有不同的种类。对每个具体工厂,分别生产一部手机需要的三个对象。通过例子来加深理解:

from abc import ABCMeta, abstractmethod

# ------抽象的产品------
class PhoneShell(metaclass=ABCMeta):
    @abstractmethod
    def show_shell(self):
        pass

class PhoneCPU(metaclass=ABCMeta):
    @abstractmethod
    def show_cpu(self):
        pass

class PhoneOS(metaclass=ABCMeta):
    @abstractmethod
    def show_os(self):
        pass
        
# ------具体的产品------
class SmallShell(PhoneShell):
    def show_shell(self):
        print('普通手机小手机壳')

class BigShell(PhoneShell):
    def show_shell(self):
        print('普通手机大手机壳')

class AppleShell(PhoneShell):
    def show_shell(self):
        print('苹果手机壳')

class SnapDragonCPU(PhoneCPU):
    def show_cpu(self):
        print('骁龙CPU')

class HuaweiCPU(PhoneCPU):
    def show_cpu(self):
        print('化为CPU')

class AppleCPU(PhoneCPU):
    def show_cpu(self):
        print('苹果CPU')

class AndroidOS(PhoneOS):
    def show_os(self):
        print('IOS系统')

class AppleOS(PhoneOS):
    def show_os(self):
        print('安卓系统')

# ------抽象的工厂------
class PhoneFactory(metaclass=ABCMeta):
    @abstractmethod
    def make_shell(self):
        pass

    @abstractmethod
    def make_cpu(self):
        pass

    @abstractmethod
    def make_os(self):
        pass

# ------具体的工厂------
class HuaweiFactory(PhoneFactory):
    def make_shell(self):
        return SmallShell()

    def make_cpu(self):
        return HuaweiCPU()

    def make_os(self):
        return AndroidOS()

class AppleFactory(PhoneFactory):
    def make_shell(self):
        return AppleShell()

    def make_cpu(self):
        return AppleCPU()

    def make_os(self):
        return AppleOS()

# ------客户端------
class Phone:
    def __init__(self, shell, cpu, os):
        self.shell = shell
        self.cpu = cpu
        self.os = os

    def show_info(self):
        print('手机信息:')
        self.shell.show_shell()
        self.cpu.show_cpu()
        self.os.show_os()

def make_phone(factory):
    shell = factory.make_shell()
    cpu = factory.make_cpu()
    os = factory.make_os()
    return Phone(shell, cpu, os)

p = make_phone(HuaweiFactory())
p.show_info()
"""
手机信息:
普通手机小手机壳
化为CPU
IOS系统
"""

抽象工厂模式的角色有:抽象工厂角色、具体工厂角色、抽象产品角色、具体产品角色和客户端。抽象工厂模式的优点是:将客户端和类的具体实现相分离;每个工厂创建了一个完整的产品系列,使得易于交换产品系列;有利于产品的一致性,即产品之间的约束关系。缺点是:难以支持新种类抽象产品

3.4. 建造者模式

建造者模式是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。角色有抽象创建者、具体创建者、指挥者和产品。建造者模式与抽象工厂模式相似,也用来创建复杂的对象。主要区别是 建造者模式着重一步步构造一个复杂对象(控制顺序)。而抽象工厂模式着重于多个系列的产品对象,写个例子来加强理解:

from abc import ABCMeta, abstractmethod

# ------产品------
class Player:
    def __init__(self, face=None, body=None, arms=None, legs=None):
        self.face = face
        self.body = body
        self.arms = arms
        self.legs = legs

    def __str__(self):
        return '%s,%s,%s,%s' % (self.face, self.body, self.arms, self.legs)

# ------抽象建造者------
class PlayerBuilder(metaclass=ABCMeta):
    @abstractmethod
    def build_face(self):
        pass

    @abstractmethod
    def build_body(self):
        pass

    @abstractmethod
    def build_arms(self):
        pass

    @abstractmethod
    def build_legs(self):
        pass

# ------具体建造者,隐藏了一个产品的内部结构------
class GirlBuilder(PlayerBuilder):
    def __init__(self):
        self.player = Player()

    def build_face(self):
        self.player.face = '漂亮的脸蛋'

    def build_body(self):
        self.player.body = '苗条的身材'

    def build_arms(self):
        self.player.arms = '细细的胳膊'

    def build_legs(self):
        self.player.legs = '大长腿'

# ------具体建造者,表示代码------
class MonsterBuilder(PlayerBuilder):
    def __init__(self):
        self.player = Player()

    def build_face(self):
        self.player.face = '绿脸'

    def build_body(self):
        self.player.body = '魁梧的身体'

    def build_arms(self):
        self.player.arms = '粗壮的胳膊'

    def build_legs(self):
        self.player.legs = '粗壮的大腿'

# ------指挥者,构造代码(构造代码和表示代码分开),可以对构造过程进行更加精细地控制------
class PlayerDirectory():
    def python之常用设计模式(创建型模式篇)(代码片段)

Python之常用设计模式一、设计模式分类1.创建型模式工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式2.结构型模式适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式3.行为型模式解释器... 查看详情

python常用模块(代码片段)

目录pandas模块SeriesDataFrameDataFrame属性处理缺失值合并数据取值matplotlib模块条形图直方图折线图散点图re模块基础的re使用贪婪模式非贪婪模式re模块高级compilematch和search分组re.split()sub和subnpandas模块pandas基于Numpy,可以看成是处理... 查看详情

如何从python中的两个文件中找到常用的模式集?(代码片段)

我有file1列为:-erweds,e3,kjuy,mnpoqwpipi,fFile2列为:-dfwewrf,pids,kj,e3rt,uyqwpo我尝试了以下代码,但它没有按预期工作:-my_set1=set(x.strip()forxin(open('file1').readlines()))print(my_set1)my_set2=set(x.strip()forxin(open('fil 查看详情

python常用的设计模式(代码片段)

文章目录1.设计模式2.面向对象设计原则3.创建型模式3.1.简单工厂模式3.2.工厂方法模式3.3.抽象工厂模式3.4.建造者模式3.5.单例模式3.6.创建型模式概述4.结构型模式4.1.适配器模式4.2.桥模式4.3.组合模式4.4.外观模式4.5.代理模式5.行为... 查看详情

python常用的设计模式(代码片段)

文章目录1.设计模式2.面向对象设计原则3.创建型模式3.1.简单工厂模式3.2.工厂方法模式3.3.抽象工厂模式3.4.建造者模式3.5.单例模式3.6.创建型模式概述4.结构型模式4.1.适配器模式4.2.桥模式4.3.组合模式4.4.外观模式4.5.代理模式5.行为... 查看详情

python常用的设计模式(代码片段)

文章目录1.设计模式2.面向对象设计原则3.创建型模式3.1.简单工厂模式3.2.工厂方法模式3.3.抽象工厂模式3.4.建造者模式3.5.单例模式3.6.创建型模式概述4.结构型模式4.1.适配器模式4.2.桥模式4.3.组合模式4.4.外观模式4.5.代理模式5.行为... 查看详情

python基础之单例模式(代码片段)

单例模式是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.单例模式的要点三个:  --某个类智能有一个实例  --他必须自行创建这个实例  --必须自行向整个系统提供这个实例在python中,我们... 查看详情

python常用的词(代码片段)

查看详情

常用设计模式(代码片段)

文章目录JAVA常用设计模式一、概念:二、分类:三、模式:1.单例设计模式2.普通工厂模式3.多个工厂方法模式4.静态工厂方法模式5.抽象工厂模式6.装饰器模式7.代理模式8.模板方法模式JAVA常用设计模式一、概念:设计... 查看详情

常用设计模式汇总(代码片段)

单例模式简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。getInstance()的返回值是一个对象的引用,并不是一个新的实例... 查看详情

java常用设计模式(代码片段)

单例模式:   即一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过其get方法获取到他们的实例。  懒汉写法(线程不安全)publicclassSingletonprivatestaticSingletonsingl... 查看详情

十种常用的设计模式(代码片段)

  转自CSDN:https://blog.csdn.net/wymrdjm/article/details/789271391.       单例模式:实现方式:a)将被实现的类的构造方法设计成private的。b)添加此类引用的静态成员变量,并为其实例化。c) 在被实... 查看详情

python常用标准库(压缩包模块zipfile和tarfile)(代码片段)

常用的标准库在我们常用的系统windows和Linux系统中有很多支持的压缩包格式,包括但不限于以下种类:rar、zip、tar,以下的标准库的作用就是用于压缩解压缩其中一些格式的压缩包。zip格式importzipfilezipfile模块操作压缩包使用ZipF... 查看详情

设计模式之单例模式(代码片段)

前言本篇博客归类于设计模式,单例模式算是我了解的不多的设计模式之一,在某些应用场景下为了节省资源,常常使用单例模式来编写代码。单例模式(SingletonPattert)是一种常用的软件设计模式,该模式的主要目的是确保在... 查看详情

常用模块2018-4-9(代码片段)

...:正则就是用来描述一类事物的规则。   (在Python中)它内嵌在Python中,并通过re模块实现。正则表达式模式被编译成 查看详情

前端常用的设计模式和使用场景(代码片段)

设计原则最重要的思想:开放封闭原则对扩展开放对修改封闭工厂模式用一个工厂函数,创建一个实例,封装创建的过程。classFoo...functionfactory():Foo//封装创建过程,这其中可能有很多业务逻辑returnnewFoo(...arguments)应用场景-jQuery`$... 查看详情

常用开源框架中设计模式使用分析(代码片段)

一、前言说起来设计模式,大家应该都耳熟能详,设计模式代表了软件设计的最佳实践,是经过不断总结提炼出来的代码设计经验的分类总结,这些模式或者可以简化代码,或者可以是代码逻辑开起来清晰,或者对功能扩展很方... 查看详情

python实现单例模式的五种写法(代码片段)

....html单例模式(SingletonPattern) 是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中, 查看详情