设计模式及创建型模式-python版

news2024/11/15 11:20:59

1 架构模式与设计模式

架构模式搞层次的设计模式, 描述系统整体结构和组织方式,设计模式是针对某个问题的解决方案,是一种解决问题的思路。

2 设计模式的分类

2.1 创建型模式

单例模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式

2.2 结构型模式

适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式

2.3 行为型模式

策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式

3 设计模式的六大原则

  • 单一职责原则:一个类只负责一个功能领域中的相应职责
  • 开闭原则:对扩展开放,对修改关闭
  • 里氏替换原则:任何基类可以出现的地方,子类一定可以出现
  • 依赖倒转原则:针对接口编程,依赖于抽象而不依赖于具体
  • 接口隔离原则:使用多个隔离的接口,比使用单个接口要好
  • 迪米特法则:一个实体应当尽量少的与其他实体发生相互作用
  • 合成复用原则:尽量使用合成/聚合的方式,而不是使用继承

4 设计模式举例

4.1 单例模式

单例模式(Singleton)用在软件运行过程中仅需要一个实例的场景,如软件的主界面, 系统全局统一管理(win 下的task manager)等。

  1. 举例
    用单例模式来模拟计算机的总线地址, 处理器中的多个线程可以调用总线地址(单例)来发送消息。
import threading
import time
class Singleton(object):
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance

class Bus(Singleton):
    lock = threading.RLock()

    def sendData(self, data):
        self.lock.acquire()
        time.sleep(3)
        print("Sending Signal Data...", data)
        self.lock.release()

class VisitEntity(threading.Thread):
    my_bus = ""
    name = ""

    def getName(self):
        return self.name

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

    def run(self):
        self.my_bus = Bus()
        self.my_bus.sendData(self.name)


if __name__ == "__main__":
    for i in range(3):
        print("Entity %d begin to run..." % i)
        my_entity = VisitEntity()
        my_entity.setName("Entity_"+str(i))
        my_entity.start()

上述代码中 Bus 继承了Singleton, 每创建一个Bus 对象, 实际上返回的都是同一个对象。

  1. 优缺点
    单例模式要求在全局只有一个实例, 可以节省内存空间;全局只有一个接入点, 可以更高的进行数据控制, 避免过多的占用;单例可以常驻内存, 减少系统开销。
    单例模式的扩展是比较困难的;赋予单例太多的职责, 某种程度上违反单一职责原则;单例模式在某种情况下会导致资源瓶颈

4.2 工厂方法模式

工厂方法模式(Factory Method Pattern)是在简单工厂模式(定义一个工厂类,根据传入的参数决定创建哪一种产品类的实例)基础上的递进。它通过定义一个创建对象的接口, 由子类决定实例化哪一个类。工厂方法模式使一个类的实例化延迟到其子类, 简言之, 就是父类提供一个接口, 子类来决定实例化哪个具体的类。

类图

  1. 举例
from abc import ABC, abstractmethod

# 定义Shape接口
class Shape(ABC):
    @abstractmethod
    def draw(self):
        pass

# 实现Circle类
class Circle(Shape):
    def draw(self):
        print("Drawing a Circle")

# 实现Square类
class Square(Shape):
    def draw(self):
        print("Drawing a Square")

# 定义ShapeFactory接口
class ShapeFactory(ABC):
    @abstractmethod
    def create_shape(self):
        pass

# 实现CircleFactory类
class CircleFactory(ShapeFactory):
    def create_shape(self):
        return Circle()

# 实现SquareFactory类
class SquareFactory(ShapeFactory):
    def create_shape(self):
        return Square()

# 使用示例
if __name__ == "__main__":
    circle_factory = CircleFactory()
    shape1 = circle_factory.create_shape()
    shape1.draw()  # 输出: Drawing a Circle

    square_factory = SquareFactory()
    shape2 = square_factory.create_shape()
    shape2.draw()  # 输出: Drawing a Square

上述例子定义了形状类产品的接口及其两个具体的实现类, 工厂接口及其两个具体的实现, 每个工厂负责生产一种形状产品。

  1. 优缺点
    解耦:将对象的创建过程与使用过程分离,降低了代码的耦合度;
    灵活性:通过子类来决定具体实例化哪个类,增加了代码的灵活性;
    扩展性:增加新的产品类时,只需添加相应的工厂类即可,不需要修改现有代码。
    类的数量增加:每增加一个产品类,都需要增加一个相应的工厂类,导致类的数量增多;
    代码复杂度提高:增加了系统的复杂性,理解起来可能会有些困难。

4.3 抽象工厂模式

在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。

抽象工厂模式(Abstract Factory)与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。

在这里插入图片描述

  1. 举例
from abc import ABCMeta, abstractmethod


class Refrigerator(metaclass=ABCMeta):
    @abstractmethod
    def use(self):
        pass


class Refrigerator1(Refrigerator):
    def use(self):
        print("Haier refrigerator")


class Refrigerator2(Refrigerator):
    def use(self):
        print("Meidi refrigerator")


class Airconditioner(metaclass=ABCMeta):
    @abstractmethod
    def go(self):
        pass


class Airconditioner1(Airconditioner):
    def go(self):
        print("Haier Airconditioner")


class Airconditioner2(Airconditioner):
    def go(self):
        print("Meidi Airconditioner")


class Factory(metaclass=ABCMeta):
    @abstractmethod
    def create_refrigerator(self):
        pass

    @abstractmethod
    def create_airconditioner(self):
        pass


class Factory1(Factory):

    def create_refrigerator(self):
        return Refrigerator1()

    def create_airconditioner(self):
        return Airconditioner1()


class Factory2(Factory):

    def create_refrigerator(self):
        return Refrigerator2()

    def create_airconditioner(self):
        return Airconditioner2()


if __name__ == '__main__':
    f = Factory1()
    r1 = f.create_refrigerator()
    r1.use()
    r2 = f.create_airconditioner()
    r2.go()

    f = Factory2()
    r1 = f.create_refrigerator()
    r1.use()
    r2 = f.create_airconditioner()
    r2.go()

上述例子定义了两个系列的产品:冰箱和空调, 每种产品又要区分不同的品牌。 定义了两个工厂实现类,分别负责生产不同品牌的产品。

  1. 优缺点
    优点
    “抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。”

“当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。”

“增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。”

缺点
“在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。”

“开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。”

4.4 建造者模式

建造者模式(Build)是把复杂对象的创建拆分成多个简单的步骤, 并将这些步骤封装在一个独立的建造者类中, 然后,我们可以使用一个指挥者类来控制建造者的调用顺序,以便在每个步骤完成后正确地构建复杂对象。

将对象的构建与其表示分离开来。这意味着我们可以使用相同的构建过程来创建不同的表示形式,而不必改变建造者的代码。

建造者模式是一种创建型设计模式,它允许您逐步构造复杂对象。与直接实例化复杂对象不同,建造者模式将对象的构造过程分解为一系列步骤,使您可以逐个处理这些步骤。

建造者模式的核心思想是将一个复杂对象的构造过程和它的表示分离开来,使得同样的构造过程可以创建不同的表示。通常情况下,一个建造者模式包括以下四个角色:

Product(产品):表示被建造的复杂对象,包含多个部件。
Builder(抽象建造者):定义构造过程的接口,包括创建各个部件的抽象方法。
ConcreteBuilder(具体建造者):实现 Builder 接口,构造和装配各个部件,同时提供一个返回产品的方法。
Director(指挥者):负责安排各个部件的构造顺序,告诉 Builder 需要创建哪些部件,以及如何组装它们。

  1. 举例
from abc import ABC, abstractmethod
class Product:
    def __init__(self):
        self.part_a = None
        self.part_b = None
        self.part_c = None


class Builder(ABC):
    def __init__(self):
        self.product = Product()

    @abstractmethod
    def build_part_a(self):
        pass

    @abstractmethod
    def build_part_b(self):
        pass

    @abstractmethod
    def build_part_c(self):
        pass


class ConcreteBuilder1(Builder):
    def build_part_a(self):
        self.product.part_a = "Part A1"

    def build_part_b(self):
        self.product.part_b = "Part B1"

    def build_part_c(self):
        self.product.part_c = "Part C1"


class ConcreteBuilder2(Builder):
    def build_part_a(self):
        self.product.part_a = "Part A2"

    def build_part_b(self):
        self.product.part_b = "Part B2"

    def build_part_c(self):
        self.product.part_c = "Part C2"


class Director:
    def __init__(self, builder):
        self.builder = builder

    def construct(self):
        self.builder.build_part_a()
        self.builder.build_part_b()
        self.builder.build_part_c()

        return self.builder.product


# Usage example
builder1 = ConcreteBuilder1()
director = Director(builder1)
product1 = director.construct()
print(product1.part_a)  # Output: Part A1
print(product1.part_b)  # Output: Part B1
print(product1.part_c)  # Output: Part C1

builder2 = ConcreteBuilder2()
director = Director(builder2)
product2 = director.construct()
print(product2.part_a)  # Output: Part A2
print(product2.part_b)  # Output: Part B2
print(product2.part_c)  # Output: Part C2

上述代码定义了一个产品类, 分成三部分。 定义了一个抽象的建造者类, 定义了抽象的方法分别来建造产品的三部分, 而后实现了两个具体的构造者, 最后定一个Director 类来调用构造者。

  1. 优缺点
    优点:

将复杂对象的构造过程和表示分离。这使得客户端可以更加简单地创建对象,同时也使得代码更加灵活和易于维护。

可以使用相同的构造过程来创建不同的对象表示。因为建造者模式将构造过程和表示分离,所以您可以使用相同的构造过程来创建不同的对象表示。这样可以大大减少代码的重复,并且使得对象表示更加易于扩展。

支持逐步构建复杂对象。建造者模式允许您逐步构建复杂对象,因为您可以分解对象构造过程为一系列简单的步骤,并逐步完成每个步骤。这样可以使得构造过程更加可控,同时也有助于代码的维护和测试。

代码结构清晰。建造者模式的代码结构清晰,并且易于理解和扩展。因为建造者模式将构造过程分解为一系列步骤,并将其封装在不同的类中,所以可以更加清晰地组织代码。

缺点

建造者模式的实现较为复杂。由于建造者模式将对象的构造过程分解为多个步骤,所以需要创建多个类来实现建造者模式。这会增加代码量和复杂度,使得代码变得更难理解和维护。

建造者模式要求建造者类必须知道产品的内部结构。由于建造者类需要创建产品的各个部分并组装它们,所以必须了解产品的内部结构。这种紧密耦合的设计使得建造者模式的扩展性和灵活性变得较差。

建造者模式不适用于创建简单的对象。由于建造者模式将对象构造过程分解为多个步骤,所以如果要创建简单的对象,建造者模式会增加代码的复杂度,使得代码变得更加冗长和难以理解。

建造者模式可能会导致对象数量增加。由于建造者模式创建的对象是由多个部件组成的,所以可能会导致对象的数量增加,从而占用更多的内存空间。

4.5 原型模式

原型模式(Prototype)是一种创建型设计模式,它的主要思想是通过复制一个已经存在的对象来创建新的对象。这个已经存在的对象被称为原型对象,新的对象通过复制原型对象的属性和状态来创建。

在原型模式中,我们需要定义一个原型接口或抽象类,这个接口或抽象类中包含了一个 clone() 方法,用于复制原型对象。具体的原型对象实现这个接口或抽象类,并实现 clone() 方法。当需要创建新的对象时,我们可以通过调用原型对象的 clone() 方法来复制它,从而创建一个新的对象。

  1. 举例
import copy
from abc import ABC, abstractmethod

# 定义原型类
class Prototype(ABC):
    @abstractmethod
    def clone(self):
        pass


# 定义具体原型类
class ConcretePrototype(Prototype):
    def __init__(self, name):
        self.name = name

    def clone(self):
        return copy.deepcopy(self)

    def __str__(self):
        return self.name


# 定义客户端类
class Client:
    def operation(self):
        # 创建原型对象
        prototype = ConcretePrototype("prototype")

        # 克隆原型对象
        clone1 = prototype.clone()
        clone2 = prototype.clone()

        # 输出克隆对象的名称
        print("Clone 1 name: " + str(clone1))
        print("Clone 2 name: " + str(clone2))


# 测试代码
client = Client()
client.operation()
  1. 优缺点
    优点:

减少对象的创建时间和消耗的资源:原型模式通过复制已有对象来创建新对象,避免了重复创建对象的过程,因此可以大幅度减少对象的创建时间和消耗的资源。

可以避免因重复创建对象而造成的资源浪费:由于原型模式可以通过复制已有对象来创建新对象,因此避免了重复创建对象而造成的资源浪费。

动态地创建对象:原型模式可以动态地创建对象,因为它不需要预先知道要创建的对象的具体类型。

可以保持对象的一致性:由于原型对象与新对象拥有相同的属性和状态,因此可以保持对象的一致性。

可以提高系统性能:由于原型模式减少了对象的创建时间和消耗的资源,因此可以提高系统性能。

缺点:

原型对象的创建过程可能比较复杂:由于原型对象需要包含所有要复制的属性和状态,因此原型对象的创建过程可能比较复杂,尤其是当属性和状态是深层嵌套的时候。

使用场景比较有限:原型模式只有当需要创建的对象可以通过复制现有对象来创建时才适用,因此它的使用场景比较有限。

可能会增加代码的复杂度:由于原型模式需要维护原型对象和具体的原型实现类,因此可能会增加代码的复杂度。

克隆方法的实现可能比较困难:实现克隆方法需要考虑对象的深浅拷贝问题,如果对象的属性和状态比较复杂,那么实现克隆方法可能比较困难。

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

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

相关文章

无人机反制:无线电侦测设备技术详解

无人机反制技术中的低空安全综合管理平台,作为守护低空安全的重要工具,集成了多种先进的技术手段和管理功能,实现了对无人机等低空飞行器的全方位、无死角监控与反制。以下是对该技术平台的详细解析: 一、技术架构与核心功能 低…

HTB-bike(SSTI模版注入)

前言 大家好,我是qmx_07,今天给大家讲解bike靶场 渗透过程 信息搜集 服务器开放了 22 ssh 和 http80端口 Wappalyzer 介绍:Wappalyzer是一种浏览器扩展程序,用于识别正在访问的网站所使用的技术栈和工具,比如使用的web框架&…

紫光同创PDS自动构建

1.开发背景 随着开发进度的不断迭代,需要对代码实行管控,FPGA代码管控也很重要,这个篇章主要是对紫光同创 PDS 开发环境下实现代码自动构建功能 2.开发需求 设计实验: 1)点击一个脚本自动编译工程 2)工程…

Fréchet Inception Distance(FID)原理

原理概述: FID 的核心思想是通过比较真实图像和生成图像在 Inception 模型特征空间中的分布差异,来评估生成模型的性能。它假设从真实数据和生成数据中提取的特征都近似服从高斯分布。 具体步骤: 特征提取:使用预训练的 Incepti…

动态加载使用Appsflyer报错Attribution data for this AppsFlyer ID is not available

1. 使用动态classloader加载AF SDK 日志:不能获取到非自然量 2024-09-03 18:07:22.350 2114-2114 ddup com.pn.cal I 找到AssetManager 2024-09-03 18:07:22.350 2114-2114 ddup com.pn.cal …

免费分享:中国煤炭资源分布图

数据详情 中国煤炭资源分布图 数据属性 数据名称:中国煤炭资源分布图 空间位置:中国 ​ 下载方法 打开数字地球开放平台网站,需要先注册登录,登录完成后,选择服务与支持下的资源下载,搜索并点击进入本…

Python加载 TorchScript 格式的 ResNet18 模型分类该模型进行预测并输出预测的类别和置信度

首先加载预训练的 ResNet18 模型。将模型设置为评估模式,以确保特定层(如 Dropout 和 BatchNorm)在评估时具有确定性的行为。创建一个形状为 (1, 3, 224, 224) 的随机张量作为示例输入。使用 torch.jit.trace 函数追踪模型在给定示例输入上的…

渗透测试靶机----DC系列 DC-1

渗透测试靶机----DC系列 DC-1 开启靶机,依旧是登陆窗,平平无奇 扫描ip,扫描端口,服务等信息 可以看到这里存在80服务,访问看看 非常明显,这里存在一个Drupal 的cms 并且是一个登录框,思路打开 …

VMware Fusion 13.6 发布下载,新增功能概览

VMware Fusion 13.6 发布下载,新增功能概览 VMware Fusion 13.6 for Mac - 领先的免费桌面虚拟化软件 适用于基于 Intel 处理器和搭载 Apple 芯片的 Mac 的桌面虚拟化软件 请访问原文链接:https://sysin.org/blog/vmware-fusion-13/,查看最…

位运算专题——常见位运算位图的使用力扣实战应用

目录 1、常见位运算 2、算法应用【leetcode】 2.1 判断字符是否唯一【面试题 】 2.1.1 算法思想【位图】 2.1.2 算法代码 2.2 只出现一次的数字 III 2.2.1 算法思想 2.2.2 算法代码 2.3 丢失的数字 2.3.1 算法思想 2.3.2 算法代码 2.4 两整数之和 2.4.1 算法思想 2…

C语言之猜数字小游戏

哈喽,大家好!我是冰淇淋加点糖。今天我们来用前面所学的知识来开发一个猜数字的小游戏,锻炼我们的编程能力和编程思维。 猜数字小游戏功能简介 1.随机生成一个1-100的数字。 2.玩家用户开始猜数字。 > 猜大了,提醒猜大了…

【爬虫软件】采集抖音博主的主页发布作品

这是我用python开发的抖音爬虫采集软件,可自动按博主抓取已发布视频。 软件界面截图: 爬取结果截图: 几点重要说明: 软件使用演示视频: https://www.bilibili.com/video/BV1Kb42187qf 完整讲解文章: ht…

虚幻5|技能栏UI优化(3)——优化技能UI并实现显示背景UI,实现技能界面设计,实现技能栏的删除和添加

实现技能栏添加:将技能界面里的技能拖到技能栏格子 一.调整,在拖出技能的时候,还会有边框 1.打开拖拽的技能格子UI 除了技能按钮,下面的子级都放到垂直框的子级,然后删除技能按钮 2.将垂直框替换成包裹框 你会发现有…

OS_线程

2024.07.01:操作系统线程学习笔记 第7节 线程 7.1 线程的基本概念7.1.1 单线程地址空间 vs 多线程地址空间 7.2 线程的状态与转换(照搬进程设计)7.2.1 线程的3种基本状态 7.3 线程管理中的数据结构7.3.1 线程的用户栈7.3.2 线程的内核栈 7.4 …

用户时长进入“零和”时代,App们如何借Push胜出?

作者 | 曾响铃 文 | 响铃说 激烈的市场竞争、快速变化的用户需求、层出不穷的新赛道新玩法……对如今移动互联网的App开发者而言,寻求用户增长的压力变得越来越大。 而与此同时,Push作为促进用户增长的关键手段之一,其执行过程中的诸多问题…

坑——fastjson将字符串转到带枚举的java对象

fastjson将不同的字符串转换成带枚举的java对象时&#xff0c;不同的字符串值转换成java对象的结果不同&#xff1b; 测试用fastjson版本&#xff1a; <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <ver…

[有彩蛋]大模型独角兽阶跃星辰文生图模型Step-1X上线,效果具说很炸裂?快来看一手实测!

先简单介绍一下阶跃星辰吧 公司的创始人兼CEO是姜大昕博士&#xff0c;他在微软担任过全球副总裁&#xff0c;同时也是微软亚洲互联网工程研究院的副院长和首席科学家。 2024年3月&#xff0c;阶跃星辰发布了Step-2万亿参数MoE语言大模型预览版&#xff0c;这是国内初创公司首…

公司监控上网记录怎么实现?监控公司局域网内电脑的上网记录,这4个方法不妨一试!

在繁忙的办公室里&#xff0c;每位员工的手指在键盘上跳跃&#xff0c;屏幕闪烁间&#xff0c;他们究竟在忙碌什么&#xff1f;是沉浸在工作的海洋中&#xff0c;还是悄然滑向了网络的另一端&#xff1f; 为了解答这一疑问&#xff0c;确保工作效率与信息安全&#xff0c;公司纷…

webpack--处理资源

在webpack.config.js中进行配置 const path require(path) module.exports {// 入口entry: ./src/main.js,// 输出output: {// 文件的输出路径path: path.resolve(__dirname, dist),// 入口文件打包输出的文件名filename: js/main.js,// 自动清空上次打包结果 原理&#xff…

Spring中基于redis stream 的消息队列实现方法

本文主要介绍了消息队列的概念性质和应用场景&#xff0c;介绍了kafka、rabbitMq常用消息队列中间件的应用模型及消息队列的实现方式&#xff0c;并实战了在Spring中基于redis stream 的消息队列实现方法。 一、消息队列 消息队列是一种进程间通信或者同一个进程中不同线程间的…