可扩展软件架构的基本 Python 设计模式

可扩展软件架构的基本 python 设计模式

作为一名拥有多年经验的 python 开发人员,我逐渐认识到设计模式在构建健壮且可扩展的软件架构方面的力量。在本文中,我将分享我对六种基本 python 设计模式的见解,这些模式在实际项目中不断证明了它们的价值。

让我们从单例模式开始。这种模式确保一个类在整个应用程序中只有一个实例。它对于管理共享资源或配置设置特别有用。这是一个简单的实现:

class singleton:    _instance = none    def __new__(cls):        if cls._instance is none:            cls._instance = super().__new__(cls)        return cls._instance    def __init__(self):        self.data = {}    def set_data(self, key, value):        self.data[key] = value    def get_data(self, key):        return self.data.get(key)

在此示例中,__new__ 方法检查实例是否已存在。如果没有,则创建一个;否则,它返回现有实例。这可确保只创建该类的一个实例。

我发现单例模式在管理数据库连接或配置设置方面特别有用。然而,明智地使用它很重要,因为它可以使单元测试更具挑战性,并将全局状态引入到您的应用程序中。

继续讨论工厂方法模式,该模式提供了一个用于在超类中创建对象的接口,允许子类更改创建的对象的类型。这是一个例子:

from abc import abc, abstractmethodclass animal(abc):    @abstractmethod    def speak(self):        passclass dog(animal):    def speak(self):        return "woof!"class cat(animal):    def speak(self):        return "meow!"class animalfactory:    def create_animal(self, animal_type):        if animal_type == "dog":            return dog()        elif animal_type == "cat":            return cat()        else:            raise valueerror("unknown animal type")

在此实现中,animalfactory 类根据输入创建不同类型的动物。当您需要创建对象而不指定其确切类时,此模式非常有用,从而使您的代码具有更大的灵活性。

立即学习“Python免费学习笔记(深入)”;

观察者模式是开发人员武器库中的另一个强大工具。它在对象之间建立一对多的依赖关系,其中多个观察者对象会收到主题对象中任何状态更改的通知。这是一个基本的实现:

class subject:    def __init__(self):        self._observers = []        self._state = none    def attach(self, observer):        self._observers.append(observer)    def detach(self, observer):        self._observers.remove(observer)    def notify(self):        for observer in self._observers:            observer.update(self._state)    def set_state(self, state):        self._state = state        self.notify()class observer:    def update(self, state):        passclass concreteobserver(observer):    def update(self, state):        print(f"state updated to: {state}")

此模式在事件驱动系统或用户界面中特别有用,其中多个组件需要对中心对象中的更改做出反应。

策略模式允许您定义一系列算法,封装每个算法,并使它们可以互换。这种模式非常适合需要在运行时在不同算法之间切换的情况。这是一个例子:

from abc import abc, abstractmethodclass sortstrategy(abc):    @abstractmethod    def sort(self, data):        passclass bubblesort(sortstrategy):    def sort(self, data):        n = len(data)        for i in range(n):            for j in range(0, n - i - 1):                if data[j] > data[j + 1]:                    data[j], data[j + 1] = data[j + 1], data[j]        return dataclass quicksort(sortstrategy):    def sort(self, data):        if len(data) <= 1:            return data        pivot = data[len(data) // 2]        left = [x for x in data if x  pivot]        return self.sort(left) + middle + self.sort(right)class sorter:    def __init__(self, strategy):        self.strategy = strategy    def sort(self, data):        return self.strategy.sort(data)

在这个例子中,我们可以通过更改传递给 sorter 类的策略来轻松地在不同的排序算法之间切换。这种模式提高了代码的可重用性,并且可以在不修改现有代码的情况下轻松添加新算法。

装饰器模式是用于扩展功能的子类化的灵活替代方案。它允许您通过将这些对象放置在包含行为的包装对象内来动态地向对象添加新行为。这是一个实现:

class coffee:    def cost(self):        return 5    def description(self):        return "simple coffee"class coffeedecorator:    def __init__(self, coffee):        self._coffee = coffee    def cost(self):        return self._coffee.cost()    def description(self):        return self._coffee.description()class milk(coffeedecorator):    def cost(self):        return self._coffee.cost() + 2    def description(self):        return f"{self._coffee.description()}, milk"class sugar(coffeedecorator):    def cost(self):        return self._coffee.cost() + 1    def description(self):        return f"{self._coffee.description()}, sugar"

当您需要动态且透明地向对象添加职责而不影响其他对象时,此模式特别有用。

最后,让我们看一下适配器模式。此模式允许具有不兼容接口的对象进行协作。当将新组件集成到现有系统中时,它特别有用。这是一个例子:

class OldPrinter:    def print_old(self, text):        print(f"[Old Printer] {text}")class NewPrinter:    def print_new(self, text):        print(f"[New Printer] {text}")class PrinterAdapter:    def __init__(self, printer):        self.printer = printer    def print(self, text):        if isinstance(self.printer, OldPrinter):            self.printer.print_old(text)        elif isinstance(self.printer, NewPrinter):            self.printer.print_new(text)

在此示例中,printeradapter 允许我们使用具有一致接口的新旧打印机。在处理遗留代码或将第三方库与不同接口集成时,这种模式非常宝贵。

这六种设计模式为构建可扩展且可维护的 python 应用程序奠定了坚实的基础。然而,重要的是要记住模式是工具,而不是规则。关键是要了解何时以及如何有效地应用它们。

根据我的经验,最成功的 python 项目是那些明智地应用这些模式来解决特定问题的项目,而不是将模式强加到代码库的各个方面。在实现这些模式时,考虑 python 特定的习惯用法和功能也很重要。

例如,python 的内置 functools.singledispatch 装饰器可用于以更具 python 风格的方式实现工厂方法模式的某种形式。类似地,python 的上下文管理器(with 语句)有时可以用作装饰器模式的替代方案,用于向对象添加行为。

实现这些模式时,保持代码尽可能简单和可读至关重要。 python 的“显式优于隐式”的哲学应该指导您的设计决策。请毫不犹豫地添加注释来解释为什么您选择了特定模式,尤其是在实现很复杂的情况下。

测试是使用设计模式时要考虑的另一个关键方面。像 singleton 这样的模式可以使单元测试更具挑战性,因此在设计代码时考虑到可测试性非常重要。考虑使用依赖注入或工厂方法来使你的类更容易测试。

随着您在这些模式方面获得更多经验,您将开始看到以强大的方式将它们结合起来的机会。例如,您可以使用工厂方法模式在策略模式实现中创建不同的策略。或者您可以使用装饰器模式向工厂创建的对象添加新行为。

请记住,设计模式并不是灵丹妙药。它们需要权衡,在应用模式之前了解这些权衡非常重要。过度使用模式可能会导致代码过于复杂,难以理解和维护。

总之,这六种 python 设计模式 – 单例、工厂方法、观察者、策略、装饰器和适配器 – 是创建可扩展和可维护的软件架构的强大工具。通过理解这些模式并明智地应用它们,您可以编写更灵活、模块化和健壮的 python 代码。与任何工具一样,关键是在正确的环境中明智地使用它们。快乐编码!

我们的创作

一定要看看我们的创作:

投资者中心 | 投资者中央西班牙语 | 投资者中德意志 | 智能生活 | 时代与回响 | 令人费解的谜团 | 印度教 | 精英开发 | js学校

我们在媒体上

科技考拉洞察 | 时代与回响世界 | 投资者中央媒体 | 令人费解的谜团 | 科学与时代媒介 | 现代印度教

以上就是可扩展软件架构的基本 Python 设计模式的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1354808.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月13日 18:48:49
下一篇 2025年12月13日 18:49:02

相关推荐

  • CSS mask属性无法获取图片:为什么我的图片不见了?

    CSS mask属性无法获取图片 在使用CSS mask属性时,可能会遇到无法获取指定照片的情况。这个问题通常表现为: 网络面板中没有请求图片:尽管CSS代码中指定了图片地址,但网络面板中却找不到图片的请求记录。 问题原因: 此问题的可能原因是浏览器的兼容性问题。某些较旧版本的浏览器可能不支持CSS…

    2025年12月24日
    900
  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 为什么设置 `overflow: hidden` 会导致 `inline-block` 元素错位?

    overflow 导致 inline-block 元素错位解析 当多个 inline-block 元素并列排列时,可能会出现错位显示的问题。这通常是由于其中一个元素设置了 overflow 属性引起的。 问题现象 在不设置 overflow 属性时,元素按预期显示在同一水平线上: 不设置 overf…

    2025年12月24日 好文分享
    400
  • 网页使用本地字体:为什么 CSS 代码中明明指定了“荆南麦圆体”,页面却仍然显示“微软雅黑”?

    网页中使用本地字体 本文将解答如何将本地安装字体应用到网页中,避免使用 src 属性直接引入字体文件。 问题: 想要在网页上使用已安装的“荆南麦圆体”字体,但 css 代码中将其置于第一位的“font-family”属性,页面仍显示“微软雅黑”字体。 立即学习“前端免费学习笔记(深入)”; 答案: …

    2025年12月24日
    000
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何解决本地图片在使用 mask JS 库时出现的跨域错误?

    如何跨越localhost使用本地图片? 问题: 在本地使用mask js库时,引入本地图片会报跨域错误。 解决方案: 要解决此问题,需要使用本地服务器启动文件,以http或https协议访问图片,而不是使用file://协议。例如: python -m http.server 8000 然后,可以…

    2025年12月24日
    200
  • 旋转长方形后,如何计算其相对于画布左上角的轴距?

    绘制长方形并旋转,计算旋转后轴距 在拥有 1920×1080 画布中,放置一个宽高为 200×20 的长方形,其坐标位于 (100, 100)。当以任意角度旋转长方形时,如何计算它相对于画布左上角的 x、y 轴距? 以下代码提供了一个计算旋转后长方形轴距的解决方案: const x = 200;co…

    2025年12月24日
    000
  • 旋转长方形后,如何计算它与画布左上角的xy轴距?

    旋转后长方形在画布上的xy轴距计算 在画布中添加一个长方形,并将其旋转任意角度,如何计算旋转后的长方形与画布左上角之间的xy轴距? 问题分解: 要计算旋转后长方形的xy轴距,需要考虑旋转对长方形宽高和位置的影响。首先,旋转会改变长方形的长和宽,其次,旋转会改变长方形的中心点位置。 求解方法: 计算旋…

    2025年12月24日
    000
  • 旋转长方形后如何计算其在画布上的轴距?

    旋转长方形后计算轴距 假设长方形的宽、高分别为 200 和 20,初始坐标为 (100, 100),我们将它旋转一个任意角度。根据旋转矩阵公式,旋转后的新坐标 (x’, y’) 可以通过以下公式计算: x’ = x * cos(θ) – y * sin(θ)y’ = x * …

    2025年12月24日
    000
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 为什么我的特定 DIV 在 Edge 浏览器中无法显示?

    特定 DIV 无法显示:用户代理样式表的困扰 当你在 Edge 浏览器中打开项目中的某个 div 时,却发现它无法正常显示,仔细检查样式后,发现是由用户代理样式表中的 display none 引起的。但你疑问的是,为什么会出现这样的样式表,而且只针对特定的 div? 背后的原因 用户代理样式表是由…

    2025年12月24日
    200
  • 如何计算旋转后长方形在画布上的轴距?

    旋转后长方形与画布轴距计算 在给定的画布中,有一个长方形,在随机旋转一定角度后,如何计算其在画布上的轴距,即距离左上角的距离? 以下提供一种计算长方形相对于画布左上角的新轴距的方法: const x = 200; // 初始 x 坐标const y = 90; // 初始 y 坐标const w =…

    2025年12月24日
    200
  • CSS元素设置em和transition后,为何载入页面无放大效果?

    css元素设置em和transition后,为何载入无放大效果 很多开发者在设置了em和transition后,却发现元素载入页面时无放大效果。本文将解答这一问题。 原问题:在视频演示中,将元素设置如下,载入页面会有放大效果。然而,在个人尝试中,并未出现该效果。这是由于macos和windows系统…

    2025年12月24日
    200
  • inline-block元素错位了,是为什么?

    inline-block元素错位背后的原因 inline-block元素是一种特殊类型的块级元素,它可以与其他元素行内排列。但是,在某些情况下,inline-block元素可能会出现错位显示的问题。 错位的原因 当inline-block元素设置了overflow:hidden属性时,它会影响元素的…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200

发表回复

登录后才能评论
关注微信