3.python设计模式【工厂模式】

news2024/11/25 7:01:50

1.简单工厂模式

  • 内容:不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品的实例。
  • 角色:
    • 工厂角色(creator)
    • 抽象产品角色(product)
    • 具体产品角色
  • UML图 :
    在这里插入图片描述
  • 举个例子:
    需求:现在需要选择支付,可以花呗支付、支付宝余额支付、微信支付,但是客户端只需要直接调用支付方法,不需要实现具体的细节。
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:
            print("花呗支付%d元" % money)
        else:
            print("支付宝余额支付" % money)

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

# 简单工厂类
class PaymentFactory:
    def create_payment(self, method):
        if method == 'alipay':
            return AliPay()
        elif method == 'wechat':
            return WechatPay()
        elif method=='huabei':
        # 这里实现了花呗支付的细节
            return AliPay(use_huabei=True)
        else:
            raise TypeError("No such payment name %s" % method)


# client
# 这样就隐藏了内部实现,客户端只需要直接调用支付方法就可以直接支付,不需要关注实现细节
pf = PaymentFactory()
p = pf.create_payment('huabei')
p.pay(100)
  • 优点
    • 隐藏了对象创建的实现细节
    • 客户端不需要修改代码
  • 缺点:
    • 违反了单一职责原则,将创建逻辑集中到一个工厂类里
    • 当添加新产品时候,需要修改工厂类代码,违反了开闭原则

2.工厂方法模式

  • 内容:定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类
  • 角色:
    • 抽象工厂角色(creator)
    • 具体工厂角色(concrete creator)
    • 抽象产品角色(product)
    • 具体产品角色(concrete product)
    • 客户端(Client)
  • UML图:
    在这里插入图片描述
  • 举个例子:
    需求:现在需要选择支付,可以花呗支付、支付宝余额支付、微信支付,但是客户端只需要直接调用支付方法,添加银行卡支付类,但是要求不能修改原来的代码(符合开闭原则)
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:
            print("花呗支付%d元" % money)
        else:
            print("支付宝余额支付" % 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 WechatPayFactory(PaymentFactory):
    def create_payment(self):
        return WechatPay()

class HuabeiPayFactory(PaymentFactory):
    def create_payment(self):
        return AliPay(use_huabei=True)

class BankPayFactory(PaymentFactory):
    def create_payment(self):
        return BankPay()

# client
pf=BankPayFactory()
p=pf.create_payment()
p.pay(100)
  • 优点:
    • 每个具体的产品都对应一个具体工厂类,不需要修改工厂类代码
    • 隐藏了对象创建的细节
  • 缺点:
    • 每增加一个具体的产品类,就必须增加一个相应的具体工厂类,代码有很大冗余

3.抽象工厂模式

  • 内容:定义一个工厂类接口,让工厂类来创建一系列相关或相互依赖的对象。相比工厂方法模式,抽象工厂模式的每个具体工厂都生产一套产品
  • 角色:
    • 抽象工厂角色(creator)
    • 具体工厂角色(concrete creator)
    • 抽象产品角色(product)
    • 具体产品角色(concrete product)
    • 客户端(Client)
  • UML图
    在这里插入图片描述
  • 举个例子:
    需求:生产一部手机,需要手机壳、CPU、操作系统三类对象进行组装,其中每类对象都有不同的种类。对每个具体工厂,分别生产一部手机所需要的三个对象。
from abc import abstractmethod, ABCMeta


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

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

class OS(metaclass=ABCMeta):
    @abstractmethod
    def show_os(self):
        pass

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

    @abstractmethod
    def make_cpu(self):
        pass

    @abstractmethod
    def make_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("苹果手机壳")

# cpu
class SnapDragonCPU(CPU):
    def show_cpu(self):
        print("骁龙CPU")
        
class MediaCPU(CPU):
    def show_cpu(self):
        print("联发科CPU")

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

# 操作系统
class Android(OS):
    def show_os(self):
        print("Android系统")

class IOS(OS):
    def show_os(self):
        print("IOS系统")

class Harmony(OS):
    def show_os(self):
        print("Harmony系统")

# --------------具体工厂--------------------
class MiFactory(PhoneFactory):
    def make_shell(self):
        return BigShell()

    def make_cpu(self):
        return SnapDragonCPU()

    def make_os(self):
        return Android()

class HuaweiFactory(PhoneFactory):
    def make_shell(self):
        return BigShell()

    def make_cpu(self):
        return MediaCPU()

    def make_os(self):
        return Harmony()


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

    def make_cpu(self):
        return AppleCPU()

    def make_os(self):
        return IOS()

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

    def show_info(self):
        print("--------手机信息--------")
        self.cpu.show_cpu()
        self.os.show_os()
        self.shell.show_shell()
    
def make_phone(factory):
    cpu = factory.make_cpu()
    os = factory.make_os()
    shell = factory.make_shell()
	return Phone(cpu, os, shell)

p1 = make_phone(iphoneFactory())
p1.show_info()

输出结果:
--------手机信息--------
苹果CPU
IOS系统
苹果手机壳

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

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

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

相关文章

Go基础快速入门

目录 一、变量相关基础语法 1、变量的定义以及赋值 2、变量的交换 3、匿名变量 4、变量的作用域 二、常量 三、基本数据类型 1、常见数据类型 2、数据类型的转换 四、运算符 五、函数 函数高级用法 函数也是一个类型 函数也是一个变量,也可以赋值 高…

视频监控汇聚平台EasyCVR视频监控录像的3种方式介绍

视频监控综合管理平台EasyCVR可以实现海量资源的接入、汇聚、计算、存储、处理等,平台具备轻量化接入能力,可支持多协议方式接入,包括主流标准协议GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Eho…

STM32MP157驱动开发——按键驱动(tasklet)

文章目录 “tasklet”机制:内核函数定义 tasklet使能/ 禁止 tasklet调度 tasklet删除 tasklet tasklet软中断方式的按键驱动程序(stm32mp157)tasklet使用方法:button_test.cgpio_key_drv.cMakefile修改设备树文件编译测试 “tasklet”机制: …

谁说dubbo接口只能Java调用,我用Python也能轻松稿定

由于公司使用基于Java语言的Dubbo技术栈,而本人对Python技术栈更为熟悉。为了使不懂JAVA代码的同学也能进行Dubbo接口层的测试,总结一个通过python实现dubbo接口调用的实现方案。 01、实现原理 根据Dubbo官方文档中提到的:dubbo可以通过tel…

裂缝处理优化策略

裂缝缺陷检测:检测道路中的裂缝,无项目背景 数据:分为两类,正常、裂缝 方案介绍 数据预处理 将原始数据标签处理为两类,正常和裂缝原始图片均为320*480,使用的显卡为2080,内存足够,不进行图片大小调整模型后处理 二分类使用softmax处理,使用最大值作为结果分类效…

操作系统第五章 错题整理

5.1 设备控制器也就是IO控制器 A对于一些简单的IO设备 控制他也许用不到IO寄存器 B 只是设备控制器与CPU(主机)交互的接口 D 只是 接口 C 对IO控制器所接收到的CPU的信息进行译码 并送到外设中 IO逻辑是个芯片 数据通路是逻辑上的 实际上还是通过总线 …

SpringBoot复习:(2)Tomcat容器是怎么启动的?

SpringApplication的run方法包含如下代码: 其中调用的refreshContext代码如下: 其中调用的refresh方法片段如下: 其中调用的refresh方法代码如下: 其中调用的super.refresh方法代码如下: public void refresh() th…

STM32CUBUMX配置RS485(中断接收)--保姆级教程

———————————————————————————————————— ⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子,使用STM32CUBEMX做了很多驱动&#x…

python selenium爬虫自动登录实例

拷贝地址:python selenium爬虫自动登录实例_python selenium登录_Ustiniano的博客-CSDN博客 一、概述 我们要先安装selenium这个库,使用pip install selenium 命令安装,selenium这个库相当于机器模仿人的行为去点击浏览器上的元素&#xff0…

24 ==比较的是地址在.equals比较的是内容

public class Demo1 {public static void main(String[] args) {byte[] arr {97,98,99};String s1 new String(arr);String s2 new String(arr);System.out.println(s1s2);System.out.println(s1.equals(s2));} }

pgvector 源码分析

简介 pgvector 库是一种用于计算向量距离的库,它的核心是提供了聚类索引,棸类索引使用的算法是 kmeans(相对于 kmeans 最主要的区别是初始化起点的位置)。 pgvector 索引的存储结构 meta page → list page → entry page inse…

vue2和vue3关于class类的绑定以及style的绑定的区别

本篇为个人笔记 1.对于class类的绑定的区别 vue2:对于vue2而言&#xff0c;所有类的绑定都是基于对象{}来进行的 例如&#xff1a;单个类绑定 <div :class"{active:isActive}"></div> 多个类绑定&#xff1a; <div :class"{active,hasError…

CNN(卷积神经网络)的实现过程详解

概要 在图像处理领域&#xff0c;CNN(卷积神经网络)处于绝对统治地位&#xff0c;但对于CNN具体是如何用神经网络实现的&#xff0c;能找到的介绍要么是一大堆数学公式&#xff0c;要么是大段晦涩的文字说明&#xff0c;读起来很是辛苦&#xff0c;想写好一片完整的而且有深度的…

【java安全】RMI

文章目录 【java安全】RMI前言RMI的组成RMI实现Server0x01 编写一个远程接口0x02 实现该远程接口0x03 Registry注册远程对象 Client 小疑问RMI攻击 【java安全】RMI 前言 RMI全称为&#xff1a;Remote Method Invocation 远程方法调用&#xff0c;是java独立的一种机制。 RM…

软件检测报告CMA/CNAS标识加盖和不加盖的区别在哪?

在生活中&#xff0c;我们经常会听到CMA(中国计量认证)和CNAS(中国合格评定国家认可委员会)这两个标识&#xff0c;尤其在软件检测领域更是如此。那么&#xff0c;软件检测报告CMA/CNAS标识加盖和不加盖有哪些区别呢CMA和CNAS认可的软件测评机构又有什么样的好处呢?本文将为您…

各电商平台api接口开发系列(数据分享)接口封装高并发

淘宝API接口就是第三方公司&#xff0c;通过淘宝开放平台接入淘宝数据&#xff0c;并进行再开发&#xff0c;将功能封装打包成函数&#xff0c;客户只需要传入参数&#xff0c;接收返回值就可以实现具体功能&#xff0c;其他1688&#xff0c;京东&#xff0c;拼多多以及海外跨境…

[Android 13]Input系列--触摸事件在应用进程的分发和处理

hongxi.zhu 2023-7-21 Android 13 前面我们已经梳理了input事件在native层的传递&#xff0c;这一篇我们接着探索input事件在应用中的传递与处理&#xff0c;我们将按键事件和触摸事件分开梳理&#xff0c;这一篇就只涉及触摸事件。 一、事件的接收 从前面的篇幅我们知道&…

STM32CubeMX v6.9.0 BUG:FLASH_LATENCY设置错误导致初始化失败

背景 今天在调试外设功能时&#xff0c;发现设置了使用外部时钟之后程序运行异常&#xff0c;进行追踪调试并与先前可以正常运行的项目进行对比之后发现这个问题可能是由于新版本的STM32CubeMX配置生成代码时的BUG引起的。 测试环境 MCU: STM32H750VBT6 STM32CubeIDE: Versi…

Android 屏幕适配各种宽高比的手机

由于android 手机的屏幕宽高比样式太多了&#xff0c;在设计UI时&#xff0c;很多时候&#xff0c;会因为宽高比&#xff0c;分辨率不同会有展示上的差异。 我是这样解决的 在activity的onCreate方法前&#xff0c;调用&#xff1a; fun screenFit(context: Context) {val me…

Gitee 上传项目到仓库(上传文件夹)

一、将仓库下载到本地 1.首先打开仓库&#xff0c;点击下载压缩包 2.将下载的压缩包解压&#xff0c;并打开&#xff0c;在当前目录下打开 二、git操作 1.在文件当前目录打开git bash 2.初始化git git init 该命令会生成一个隐藏的.git文件夹 如果不是第一次使用&#…