python之常用设计模式(创建型模式篇)(代码片段)

Aspirantlu Aspirantlu     2023-01-23     625

关键词:

Python之常用设计模式

一、设计模式分类

1. 创建型模式

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

2. 结构型模式

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

3. 行为型模式

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

二、创建型模式

1. 简单工厂模式

  • 内容

    • 不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例。
  • 角色(类)

    • 工厂角色(Creator)
    • 抽象产品角色(Product)
    • 具体产品角色(Concrete Product)
from abc import ABCMeta, abstractmethod


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


class AliPay(Payment):
    def __init__(self, use_huabei=False) -> None:
        self.use_huabei = use_huabei

    def pay(self, money):
        if self.use_huabei:
            print(f"花呗支付money元")
        else:
            print(f"支付宝余额支付money元")


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


class PaymentFactory:
    """生产支付对象的工厂类 用于生产AliPay或WechatPay对象"""
    def createPayment(self, method):
        if method == "alipay":
            return AliPay()
        elif method == "huabei":
            return AliPay(use_huabei=True)
        elif method == "wechat":
            return WechatPay()
        else:
            raise TypeError(f"No such payment named method")


# client
pf = PaymentFactory()
p = pf.createPayment("huabei")
p.pay(100)

上面例子中,工厂角色(类)是PaymentFactory,抽象产品角色是Payment,具体产品角色是AliPay和WechatPay。

  • 优点
    • 隐藏了对象创建的实现细节
    • 客户端不需要修改代码
  • 缺点
    • 违反了单一职责原则,将创建逻辑几种到一个工厂类里
    • 当添加新产品时,需要修改工厂类代码,违反了开闭原则

2. 工厂方法模式

  • 内容

定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类。

  • 角色
    • 抽象工厂角色(Creator)
    • 具体工厂角色(Concrete Creator)
    • 抽象产品角色(Product)
    • 具体产品角色(Concrete Product)
from abc import ABCMeta, abstractmethod


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


class AliPay(Payment):
    def __init__(self, use_huabei=False) -> None:
        self.use_huabei = use_huabei

    def pay(self, money):
        if self.use_huabei:
            print(f"花呗支付money元")
        else:
            print(f"支付宝余额支付money元")


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


class BankPay(Payment):
    def pay(self, money):
        print(f"银联支付money元")


class PaymentFactory(metaclass=ABCMeta):
    @abstractmethod
    def createPayment(self):
        pass


class AliPayFactory(PaymentFactory):
    def createPayment(self):
        return AliPay()


class WechatPayFactory(PaymentFactory):
    def createPayment(self):
        return WechatPay()


class HuaBeiFactory(PaymentFactory):
    def createPayment(self):
        return AliPay(use_huabei=True)


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


# client
pf = HuaBeiFactory()
p = pf.createPayment()
p.pay(100)

上面例子中,抽象工厂角色是PaymentFactory,具体工厂角色是AliPayFactory、WechatPayFactory、HuaBeiFactory和BankPayFactory,抽象产品角色是Payment,具体产品角色是AliPay、WechatPay、BankPay。

  • 优点
    • 每个具体产品都对应一个具体工厂类,不需要修改工厂类代码
    • 隐藏了对象创建的实现细节
  • 缺点
    • 每增加一个具体产品类,就必须增加一个相应的具体工厂类

3. 抽象工厂模式

  • 内容

定义一个工厂类接口,让工厂子类来创建一系列相关或相互依赖的对象。
举个例子:生产一部手机,需要手机壳、CPU、操作系统三类对象进行组装,其中每类对象都有不同的种类。对每个具体工厂,分别生产一部手机所需要的三个对象。
相比工厂方法模式,抽象工厂模式中的每个具体工厂都生产一套产品。

  • 角色
    • 抽象工厂角色(Creator)
    • 具体工厂角色(Concrete Creator)
    • 抽象产品角色(Product)
    • 具体产品角色(Concrete Product)
    • 客户端(Client)
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("苹果手机壳")


class MediaTekCPU(CPU):
    def show_cpu(self):
        print("联发科CPU")


class SnapDragonCPU(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 MiFactory(PhoneFactory):
    def make_shell(self):
        return BigShell()

    def make_cpu(self):
        return SnapDragonCPU()

    def make_os(self):
        return Android()


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) -> None:
        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(MiFactory())
p1.show_info()

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

4. 建造者模式

  • 内容

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

  • 角色
    • 抽象建造者(Builder)
    • 具体建造者(Concrete Builder)
    • 指挥者(Director)
    • 产品(Product)
from abc import abstractmethod, ABCMeta


class Player():
    """产品"""
    def __init__(self, face=None, body=None, arm=None, leg=None) -> None:
        self.face = face
        self.body = body
        self.arm = arm
        self.leg = leg

    def __str__(self) -> str:
        return f"self.face,self.body,self.arm,self.leg"


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

    @abstractmethod
    def build_body(self):
        pass

    @abstractmethod
    def build_arm(self):
        pass

    @abstractmethod
    def build_leg(self):
        pass


class SexyGirlBuilder(PlayerBuilder):
    """具体建造者"""
    def __init__(self) -> None:
        self.player = Player()

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

    def build_body(self):
        self.player.body = "苗条"

    def build_arm(self):
        self.player.arm = "漂亮胳膊"

    def build_leg(self):
        self.player.leg = "大长腿"


class MonsterBuilder(PlayerBuilder):
    """具体建造者"""
    def __init__(self) -> None:
        self.player = Player()

    def build_face(self):
        self.player.face = "怪兽脸"

    def build_body(self):
        self.player.body = "怪兽身材"

    def build_arm(self):
        self.player.arm = "长毛的胳膊"

    def build_leg(self):
        self.player.leg = "长毛的腿"


class PlayerDirector():
    """指挥者 控制组装顺序"""
    def builder_player(self, builder):
        builder.build_body()
        builder.build_face()
        builder.build_arm()
        builder.build_leg()
        return builder.player


# client
builder = SexyGirlBuilder()
director = PlayerDirector()
p = director.builder_player(builder)
print(p)

建造者模式与抽象工厂模式相似,也用来创建复杂对象。主要区别是建造者模式着重一步步构造一个复杂对象,而抽象工厂模式着重于多个系列的产品对象。

  • 优点
    • 隐藏了一个产品的内部结构和装配过程
    • 将构造代码与表示代码分开
    • 可以对构造过程进行更精细的控制

5. 单例模式

  • 内容

保证一个类只有一个实例,并提供一个访问它的全局访问点。

  • 角色
    单例(Singleton)
from abc import abstractmethod, ABCMeta


class Singleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance


class MyClass(Singleton):
    def __init__(self, a) -> None:
        self.a = a


a = MyClass(10)
b = MyClass(20)
print(a.a)  # 20
print(b.a)  # 20

  • 优点
    • 对唯一实例的受控访问
    • 单例相当于全局变量,但防止了命名空间被污染

6. 创建型模式总结

  1. 抽象工厂模式和建造者模式相比于简单工厂模式和工厂方法模式而言更灵活也更复杂。
  2. 通常情况下、设计以简单工厂模式或工厂方法模式开始,当你发现设计需要更大的灵活性时,则像更复杂的设计模式演化。

创建型设计模式之原型模式(代码片段)

...式的原型模式与单例模式是密不可分的,这也是最常用的设计模式之一。原型模式是一种非常简单的设计模式。这里除了基本介绍和演示,还详细介绍了Java中原型模式的本质。一、介绍  同样,先来看一下《研磨设计模式》... 查看详情

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.行为... 查看详情

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

单例模式单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的一个类只有一个实例。即一个类只有一个对象实例。简单的理解:保证这一个类... 查看详情

java进阶篇设计模式之十四-----总结篇(代码片段)

前言本篇是讲述之前学习设计模式的一个总结篇,其目的是为了对这些设计模式的进行一个提炼总结,能够通过查看看此篇就可以理解一些设计模式的核心思想。设计模式简介什么是设计模式设计模式是一套被反复使用的、多数... 查看详情

技能篇:实际开发常用设计模式(代码片段)

创建型单例模式单例对象能节约系统资源,一个对象的创建和消亡的开销可能很小。但是日常的服务接口,就算是一般小公司也有十几万的QPS吧。每一次的功能运转都创建新的对象来响应请求,十几万对象的创建和销... 查看详情

设计模式之实验二:创建型设计模式实验(代码片段)

实验项目二:创建型设计模式实验(1)实验目的与原理①结合实例,熟练绘制创建型设计模式结构图。②结合实例,熟练使用Java面向对象编程语言实现创建型设计模式。③通过编程实践,理解每一种创建型设计模式... 查看详情

设计模式之工厂模式(代码片段)

工厂模式简介:工厂模式(FactoryPattern)是Java中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用... 查看详情

设计模式之简单工厂模式(创建型)(代码片段)

定义简单工厂模式又称静态工厂模式。可以根据参数的不同返回不同类的实例。定义一个类来创建其它类的实例。角色简单工厂模式包含如下角色Factory:工厂角色Product:抽象产品角色ConcreteProduct:具体产品角色简单实例publicabst... 查看详情

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.行为... 查看详情

设计模式之建造者模式(创建型)(代码片段)

模式定义建造者模式属于23种设计模式中的创建型模式,可以理解为创建对象的一种很好的方法。所谓建造者模式就是将组件和组件的组件过程分开,然后一步一步建造一个复杂的对象。所以建造者模式又叫生成器模式。建造者... 查看详情

23种设计模式创建型模式详细介绍之工厂模式(代码片段)

23种设计模式【创建型模式】详细介绍之【工厂模式】设计模式的分类和应用场景总结工厂模式抽象工厂模式设计模式的分类和应用场景总结可以查看专栏设计模式:设计模式工厂模式工厂模式是一种创建型设计模式,它... 查看详情

23种设计模式创建型模式详细介绍之工厂模式(代码片段)

23种设计模式【创建型模式】详细介绍之【工厂模式】设计模式的分类和应用场景总结工厂模式抽象工厂模式设计模式的分类和应用场景总结可以查看专栏设计模式:设计模式工厂模式工厂模式是一种创建型设计模式,它... 查看详情

创建型模式之抽象工厂模式(代码片段)

介绍参见菜鸟教程下面给出C++的一个例子#include<iostream>#include<memory>usingnamespacestd;//shap接口classshappublic:virtualvoiddraw();;//shap接口的实现类classRect:publicshappublic:voiddraw()std::cout<<" 查看详情

java设计模式之创建型:工厂模式详解(简单工厂+工厂方法+抽象工厂)(代码片段)

        在面向对象编程中,创建对象实例最常用的方式就是通过new操作符构造一个对象实例,但在某些情况下,new操作符直接生成对象会存在一些问题。举例来说,对象的创建需要一系列的步骤:可能需... 查看详情

从零开始学习java设计模式|创建型模式篇:单例设计模式(代码片段)

从本讲开始,咱们就要开始正式学习23种设计模式了。当然,我们得按照顺序来学,首先先来学习23种设计模式里面的第一类模式,即创建型模式。创建型模式的主要关注点是"怎样创建对象?",它的... 查看详情

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

...介绍一种创建型模式:单例模式这是一种比较容易理解的设计模式,可以理解为创建对象的一种很好的做法。可以尽量避免创建过多的对象,给JVM造成很大的负载。应用场景单例模式的一些应用场景:1、比如数据连接类,这是... 查看详情