Python(10):常见的4种设计模式(单例/工厂/策略/观察者)

news2024/11/26 19:44:28

文章目录

  • 一、单例模式
  • 二、工厂模式
  • 三、策略模式
  • 四、观察者模式

程序中设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案,这些解决方案是众多软件按开发人员经过相当长的一段时间的实验和错误总结出来的。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码的可靠性。

一、单例模式

标题解释
使用该模式的目的是确保某一个类只有一个实例存在
适用场景当一个类只能有一个实例而客户可以从一个众所周知的访问点访问它时
优点对唯一实例的受控访问,相当于全局变量,但是又可以防止此变量被篡改
class A:
    a = None

    def __new__(cls, *args, **kwargs):
        if cls.a is None:
            cls.a = object.__new__(cls)
        return cls.a

    def __init__(self, name):
        self.name = name

    def __call__(self, *args, **kwargs):
        print(self.name)


if __name__ == '__main__':
    a = A('张三')
    b = A('李四')
    a()
    b()


结果:

在这里插入图片描述
图示一下:

在这里插入图片描述

二、工厂模式

标题解释
使用定义一个创建对象的接口,让子类决定实例化哪个接口
适用场景需要生产多种,大量复杂对象的时候,需要降低代码耦合度的时候,当系统中的产品类经常需要扩展的时候
优点每个具体的产品都对应一个具体工厂,不需要修改工厂类的代码,工厂类可以不知道它所创建的具体的类,隐藏了对象创建的实现细节
缺点每增加一个具体的产品类,就必须增加一个相应的工厂类

代码示例:

class BC:
    def run(self):
        print('奔驰在此')


class AD:
    def run(self):
        print('奥迪在此')


class BMW:
    def run(self):
        print('宝马在此')


class Factory:
    def whatcar(self, name):
        if name == '奔驰':
            return BC()
        elif name == '奥迪':
            ad = AD()
            return ad
        else:
            return BMW()


if __name__ == '__main__':
    a = Factory().whatcar('奔驰').run()
    b = Factory().whatcar('宝马').run()
    c = Factory().whatcar('奥迪').run()

结果:
在这里插入图片描述


三、策略模式

标题解释
使用定义一系列的算法把它们一个个封装起来,并且使它们可相互替换.该模式使得算法可独立于使用它的客户而变化
适用场景:许多相关的类仅仅是行为有异,需使用一个算法的不同变体,算法使用了客户端无需知道的数据,一个类中的多个行为以多个条件语句存在可以将其封装在不同的策略类中
优点定义了一系列可重用的算法和行为,消除了一些条件语句,可提供相同行为的不同实现
缺点客户必须了解不同的策略,策略与上下文之间的通信开销,增加了对象的数目

代码示例:

class c1:
    def go(self):
        return 1


class c2:
    def go(self):
        return 2


if __name__ == '__main__':
    type = int(input('请输入要用的算法(1/2):'))
    if type == 1:
        print(c1().go())
    elif type == 2:
        print(c2().go())

结果:
在这里插入图片描述


四、观察者模式

标题解释
定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并被自动更新.观察者模式又称为’发布订阅’模式
适用场景:当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,这时候将两者封装在独立的对象中以使它们各自独立的改变和复用 ① 当一个对象的改变需要同时改变其他对象,而且不知道具体有多少对象以待改变 ②当一个对象必须通知其他对象,而又不知道其他对象是谁,即这些对象之间是解耦的
优点:目标和观察者之间的耦合最小,支持广播通信
缺点:多个观察者之间互不知道对方的存在,因此一个观察者对主题的修改可能造成错误的更新
class Boss:
    def __init__(self):
        self.observers = []
        self.command = ''

    def attach(self, ob):
        self.observers.append(ob)

    def notify(self):
        for ob in self.observers:
            ob.message()  # 调用对象的update方法


class Employee():
    def __init__(self, name, boss):
        self.name = name
        self.boss = boss

    def message(self):
        print(f'{self.name},你的老板发来命令:{self.boss.command}')


if __name__ == '__main__':
    boss = Boss()
    zs = Employee('张三', boss)
    boss.attach(zs)
    boss.command = '你被开除了'
    boss.notify()

结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1590875.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

对于所有对象都通用的方法⭐良好习惯总结

对于所有对象都通用的方法⭐良好习惯总结 Object是每个类的父类,它提供一些非final方法:equals、hashCode、clone、toString、finalize... 这些方法在设计上是可以被子类重写的,但是重写前需要遵守相关的规定,否则在使用时就可能…

MYBATIS获取参数值

MYBATIS最核心的莫过于动态的获取各种的参数值, 为了将来更好的使用MYBATIS进行开发, 我们必须先打好 "获取参数值" 这一基础 一. MYBATIS获取参数值的两种情况: 1.${} 实质:字符串的拼接 注解:${}使用的字符串拼接的方式拼接SQL语句, 所以, 如果其中出现了字符串…

23. 【Android教程】轮播滚动视图:ViewFlipper

轮播视图 ViewFlipper 是 Android 从第一个版本就开始提供的 UI 控件,它能够承载多个 View,但一个时机只会有一个 View 展示在屏幕上。通过 ViewFlipper 我们可以实现很多常见的带有展示类型的功能,类似 Gallery、轮播图、导航栏、广告banner…

基于Springboot+Vue的Java项目-旅游网站系统(附演示视频+源码+LW)

大家好!我是程序员一帆,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:Java毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计 &am…

C# WinForm —— 项目目录结构

1. WinForm 应用程序项目 Properties:属性文件夹存放了一个自动生成的类文件AssemblyInfo.cs,保存了一些应用程序集的一些信息引用存放了一些为应用程序提供所需的,某些功能的一些程序集(dll文件)等添加引用&#xff…

一些知识点小细节

当遇到的问题有关逆序输出,可以转换一下思想,就是使用for循环的时候,i的初始化是从数组或者是字符串的最后一个,然后注意设置循环结束的条件,最重要的是不要忘记i--;而不是I; 注意:当要逆序输出…

蚓链赋能企业拥有“数据能力”会带来哪些变革?

数字时代,对任何一家无论大小的企业,数据都是不可或缺的资源和工具。蚓链赋能企业拥有“数据能力”将会给企业带来哪些变革呢? 首先,将会提高企业的业务效率,通过数据分析和挖掘,企业可以更好地了解客户需…

Composer安装与配置

Composer,作为PHP的依赖管理工具,极大地简化了PHP项目中第三方库的安装、更新与管理过程。本文将详细介绍Composer的安装步骤、基本配置方法,以及一些实用的操作示例,帮助读者快速上手并熟练运用Composer。 一、Composer安装 环…

redis 数据迁移到rds2214(TongRDS-2.2.1.3.Load版 by lqw)

​ 文章目录 一.备份redis文件 vi redis.conf ,看看有没有这两行设置,有的话改成跟下面的一致: appendonly yes appendfilename “appendonly.aof” 之后连接redis客户端,输入INFO persistence,如图所示即为开启成功…

中国历年GDP统计-探数API统计

数据介绍 时间维度:1978年-2021年 单位:亿元 该数据来源于国家统计局发布的中国统计年鉴2021,为按当年价格计算的中国历年GDP以及人均GDP。 数据说明: 数据来源于国家统计局。

SpringBoot-自定义Starter精华版

SpringBoot自定义Starter精华版 一、自定义 Starter 分析 项目首先加载 starter,starter加载自动配置类,然后再通过配置绑定对象读取配置属性,注册组件。 二、实现步骤 ​ 开发的自定义 Starter 需求是,项目依赖starterTest-spring-boot-s…

重生奇迹MU圣导师与弓箭手职业对比

职业定位对比 在职业定位上,弓箭手是一个远程物理输出职业,不过弓箭手也有一定的辅助能力,可以为队友提供控场效果,还能为队友提供一个攻击力加成BUFF。同时弓箭手也是一个非常需要操作的职业,想要玩好这个职业&#…

智能体Agent是AI时代普通人可参与的第一个红利机会

自从生成式 AI 兴起,掌握 prompt 能让 AI 工具更好为我们服务。而智能体的出现,让 AI 的使用门槛更是不断降低——都不用写 Prompt 了,直接用智能体就行了。 智能体Agent是AI时代普通人可参与的第一个红利机会© 由 ZAKER科技 提供 前几…

基于java+springboot+vue实现的药品管理系统(文末源码+Lw)23-297

摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,药品信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广…

Go 自定义14位时间类型 yyyyMMddHHmmss

目录 功能 代码 功能 数据库或者接口时间类型,经常会使用14位的时间格式。每次都转换有点麻烦。可以自定义一个时间类型。 自定义类型需要实现json接口中的MarshalJSON与UnmarshalJSON两个函数,这样在做json编码解码时就会自动转为14位的时间格式了。…

【力扣】142. 环形链表 II

142. 环形链表 II 题目描述 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环&am…

第6章:6.3.3 正则表达式的应用 (MATLAB入门课程)

讲解视频:可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇(数学建模清风主讲,适合零基础同学观看)_哔哩哔哩_bilibili 到目前为止,我们已经系统地介绍了正则表达式的基本语…

Bytebase 2.15.0 - GitOps 整体升级

🔔 GitOps 整体升级 新版 GitOps 和之前版本不兼容,如果需要升级协助,请联系我们。 使用访问令牌进行身份验证。支持项目中配置多个 VCS 连接器。支持在 VCS 连接器中指定数据库分组为目标(默认情况下应用于项目中的所有数据库&…

uni-app实现下拉刷新

业务逻辑如下: 1.在滚动容器中加入refresher-enabled属性,表示为开启下拉刷新 2.监听事件,添加refresherrefresh事件 3.在事件监听函数中加载数据 4.关闭动画,添加refresher-triggered属性,在数据请求前开启刷新动画…

自营商城上货采集,上货软件采集(淘宝1688)接口

自营商城上货采集及上货软件采集涉及到淘宝和1688等平台的接口时,主要流程包括确定数据源、申请API权限、编写自动化采集脚本以及后续的数据处理和商城上货。 taobao.item_get-获取淘宝商品数据接口返回值说明 1.请求方式:HTTP POST GET (复…