【常用设计模式】待补充

Github仓库地址

概述

23中设计模型分为常见的三大类:创建型模式、结构型模式和行为型模式

image-20230605140632440

创建型模式

简单工厂模式

描述

简单工厂模式不是23中设计模式中的。简单工厂模式不直接向客户端暴露对象创建的细节,而是通过一个工厂类来负责创建产品类的实例

角色

  1. 抽象产品角色:给具体产品角色提供接口规范
  2. 具体产品角色:实现同类内容的不同实现结果
  3. 工厂角色:负责传入不同的参数,调用不同的具体产品角色,实现不同的功能

实现

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 == True:
            print("花呗支付了{0}元!".format(money))
        else:
            print("支付宝余额支付了{0}元!".format(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 == 'WechatPay':
            return WechatPay()
        elif method == 'HuabeiPay':
            return Alipay(use_huabei=True)
        else:
            raise TypeError('No such payment named %s' % method)

优点

  1. 隐藏了对象(具体产品角色)创建的细节
  2. 面对新的具体产品对象,客户端(上层)不需要修改代码,仅在参数传递上有所改动

缺点

  1. 违反了单一职责原则:工厂类对象中包含了多种具体产品角色的选择逻辑
  2. 违反了开放封闭原则:当新增具体产品角色时,需要对工厂类对象进行修改

工厂方法模式

描述

在简单工厂模式的基础上,定义一个抽象工厂和具体工厂的角色,从而让客户端决定具体实例化哪一个产品

角色

  1. 抽象产品角色:给具体产品角色的创建提供接口规范
  2. 具体产品角色:创建不同的产品
  3. 抽象工厂角色:给具体产品角色的调用提供接口规范
  4. 具体工厂角色:创建不同的工厂

实现

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 == True:
            print("花呗支付了{0}元!".format(money))
        else:
            print("支付宝余额支付了{0}元!".format(money))
            
class WechatPay(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 Alipay()

class HuabeiFactory(PaymentFactory):
    def create_payment(self):
        return Alipay(use_huabei=True)
# 客户端调用
hfp = HuabeiFactory().create_payment()
hfp.pay(100)

优点

  1. 每个具体产品一一对应一个具体工厂类,不需要修改具体工厂类代码
  2. 隐藏具体产品对象创建的实现细节

缺点

  1. 每增加一个具体产品类,需要增加一个相应的具体工厂类

抽象工厂模式

描述

在工厂模式的基础上又进行了一层抽象提取

角色

  1. 抽象产品角色:给具体产品角色的创建提供接口规范
  2. 具体产品角色:创建不同的产品
  3. 抽象工厂角色:给具体产品角色的调用提供接口规范
  4. 具体工厂角色:创建不同的工厂
  5. 客户端

实现

from abc import ABCMeta, abstractmethod

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

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

class PhoneOS(metaclass=ABCMeta):
    @abstractmethod
    def show_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 SnapDragonCPU(PhoneCPU):
    def show_cpu(self):
        print('骁龙CPU')

class HuaweiCPU(PhoneCPU):
    def show_cpu(self):
        print('化为CPU')

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

class AndroidOS(PhoneOS):
    def show_os(self):
        print('IOS系统')

class AppleOS(PhoneOS):
    def show_os(self):
        print('安卓系统')
# 抽象工厂角色
class PhoneFactory(metaclass=ABCMeta):
    @abstractmethod
    def make_shell(self):
        pass

    @abstractmethod
    def make_cpu(self):
        pass

    @abstractmethod
    def make_os(self):
        pass
# 具体工厂角色
class HuaweiFactory(PhoneFactory):
    def make_shell(self):
        return SmallShell()

    def make_cpu(self):
        return HuaweiCPU()

    def make_os(self):
        return AndroidOS()

# 对具体工厂的实现加以限制,避免随意使用:苹果手机只能用苹果的CPU
class AppleFactory(PhoneFactory):
    def make_shell(self):
        return AppleShell()

    def make_cpu(self):
        return AppleCPU()

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

    def show_info(self):
        print('手机信息:')
        self.shell.show_shell()
        self.cpu.show_cpu()
        self.os.show_os()


def make_phone(factory):
    shell = factory.make_shell()
    cpu = factory.make_cpu()
    os = factory.make_os()
    return Phone(shell, cpu, os)
# 用户端调用
p = make_phone(HuaweiFactory())
p.show_info()

优点

  1. 客户端与类的具体实现相分离
  2. 每个工厂都能创建一个完整的产品系列
  3. 产品之间存在约束关系:有利于产品的一致性

缺点

  1. 难以支持新种类的(抽象)产品:例如要增加内存版本的生产信息(抽象产品需要新增),则所有的工厂都需要修改(抽象工厂需要修改)

建造者模式

描述

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

角色

  1. 产品
  2. 抽象创建者
  3. 具体创建者
  4. 指挥者

实现

from abc import ABCMeta, abstractmethod

# 产品
class Player_Product:
    def __init__(self, face=None, body=None, arms=None, legs=None):
        self.face = face
        self.body = body
        self.arms = arms
        self.legs = legs

    def __str__(self):
        return '%s,%s,%s,%s' % (self.face, self.body, self.arms, self.legs)
# 抽象建造者
class PlayerBuilder(metaclass=ABCMeta):
    @abstractmethod
    def build_face(self):
        pass

    @abstractmethod
    def build_body(self):
        pass

    @abstractmethod
    def build_arms(self):
        pass

    @abstractmethod
    def build_legs(self):
        pass
# 具体建造者,隐藏了一个产品的内部结构
class GirlBuilder(PlayerBuilder):
    def __init__(self):
        self.player = Player_Product()

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

    def build_body(self):
        self.player.body = '苗条的身材'

    def build_arms(self):
        self.player.arms = '细细的胳膊'

    def build_legs(self):
        self.player.legs = '大长腿'


class MonsterBuilder(PlayerBuilder):
    def __init__(self):
        self.player = Player_Product()

    def build_face(self):
        self.player.face = '绿脸'

    def build_body(self):
        self.player.body = '魁梧的身体'

    def build_arms(self):
        self.player.arms = '粗壮的胳膊'

    def build_legs(self):
        self.player.legs = '粗壮的大腿'
# 指挥者,构造代码(构造代码和表示代码分开),可以对构造过程进行更加精细地控制
class PlayerDirectory():
    def builder_player(self, builder):
        """
        隐藏了装配过程
        :param builder:
        :return:
        """
        builder.build_face()
        builder.build_body()
        builder.build_arms()
        builder.build_legs()
        return builder.player
# 用户端调用
builder = GirlBuilder()
director = PlayerDirectory()
p = director.builder_player(builder)
print(p)

优点

  1. 具体建造者之间独立,容易扩展
  2. 便于控制细节风险

缺点

  1. 产品需要有共同点,这些共同点通过不同的组合可以组合出不同的产品
  2. 如果这些共同点可以组成极多的产品,则会有很多的产品建造者

抽象工厂 VS 建造者模式

  1. 前者注重整体:每一个具体工厂都能制造一个产品:华为手机工厂、苹果手机工厂、锤子手机工厂
  2. 后者注重局部:产线就一个(指挥者),根据搭配(具体建造者)制造不同的产品:用ardroid、麒麟、小手机壳,就生产华为手机;用ios、M2、大手机壳,就生产苹果手机

理解

https://zhuanlan.zhihu.com/p/405399335

这个描述绝了

抽象工厂模式像是从某宝输入“电脑”的关键字直接进行购买,获得一个已经完整的电脑。

创建者模式,更像是“找个一个电脑的外壳,往该外壳内一步一步的组装零件,最后得到一个完整的电脑”。

单例模式

描述

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

角色

  1. 单例

实现

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):
        self.a = a
# 用户端调用
ms1 = MyClass(1)
ms2 = MyClass(2)
print(ms1.a, ms2.a)
print(id(ms1), id(ms2))

优点

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

结构型模式

适配器模式

描述

将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

角色

  1. 目标接口
  2. 待适配的类
  3. 适配器

实现1:多继承

from abc import ABCMeta, abstractmethod

# 目标接口:抽象方法
class Payment(object, metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass

# 目标接口:具体实现
class Alipay(Payment):
    def pay(self, money):
        print('支付了%d' % money)
# 待适配的类
class BankPay():
    def cost(self, money):
        print('银联支付了%d' % money)
# 类适配器
class PaymentAdapter(Payment, BankPay):
    """
    把不兼容cost转换成pay
    """

    def pay(self, money):
        self.cost(money)
# 客户端调用
p = PaymentAdapter()
p.pay(100)

优点

  1. 想使用一个已经存在地类,而它的接口不符合要求
  2. 适用于单个对象需要适配的场景:多继承的适配方式,一个类适配器只能适配一个待适配的类

实现2:组合

from abc import ABCMeta, abstractmethod

# 目标接口:抽象方法
class Payment(object, metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass

# 目标接口:具体实现
class Alipay(Payment):
    def pay(self, money):
        print('支付了%d' % money)
# 待适配的类
class BankPay():
    def cost(self, money):
        print('银联支付了%d' % money)

# 待适配的类
class ApplePay():
    def cost(self, money):
        print('苹果支付了%d' % money)
# 对象适配器
class PaymentAdapter(Payment):
    def __init__(self, payment):
        self.payment = payment

    def pay(self, money):
        self.payment.cost(money)
# 客户端调用
p = PaymentAdapter(ApplePay())
p.pay(100)
p = PaymentAdapter(BankPay())
p.pay(100)

优点

  1. 想使用多个已经存在地类,而他们的接口不符合要求,但他们的接口都一致
  2. 适用于多个对象需要适配的场景:组合的适配方式,一个类适配器可以适配多个接口一致的待适配的类

桥模式

有难度,暂时跳过

https://blog.csdn.net/hbuxiaofei/article/details/106888178

组合模式

外观模式

代理模式


行为型模式

责任链模式

观察者模式

策略模式

模板方法模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值