Python之最常用的16种设计模式

文章目录

  • 一、设计模式与面向对象介绍
    • 1.1 设计模式
    • 1.2 复习:面向对象
    • 1.3 接口
  • 二、面向对象设计SOLID原则
  • 三、设计模式分类
  • 四、创造型模式
    • 4.1 简单工厂模式
    • 4.2 工厂方法模式
    • 4.3 抽象工厂模式
    • 4.4 建造者模式
    • 4.5 单例模式
    • 4.6 创建型模式小结
  • 五、结构型模式
    • 5.1 适配器模式
    • 5.2 桥模式
    • 5.3 组合模式
    • 5.4 外观模式
    • 5.5 代理模式
  • 六、行为型模式
    • 6.1 责任链模式
    • 6.2 观察者模式
    • 6.3 策略模式
    • 6.4 模板方法模式

一、设计模式与面向对象介绍

1.1 设计模式

  • 设计模式:对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计

1.2 复习:面向对象

  • 面向对象的三大特性:
    • 封装:
      1. Python中将属性与方法封装至对象中
      2. Python类中的私有属性与私有方法
    • 继承
    • 多态:Python天生支持多态

1.3 接口

  • 接口:若干抽象方法的集合
    • 作用:限制实现接口的类必须按照接口给定的调用方式实现这些方法;对高层模块隐藏了类的内部实现

二、面向对象设计SOLID原则

  • 开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

  • 里氏替换原则:所有引用父类的地方必须能透明地使用其子类的对象

  • 依赖倒置原则:高层模块不应该依赖底层模块,二者都应该依赖其抽象(接口方法);抽象(接口方法)不应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程

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

class Alipay(Payment):
    def pay(self, money):
        pass

class WechatPay(Payment):
    def pay(self, money):
        pass

def pay(payment): # 里氏替换原则
    payment.pay()
  • 接口隔离原则:使用多个专门的接口,而不是使用单一的总接口,即客户端(高层代码)不应该依赖那些它不需要的接口
class LandAnimal(metaclass=ABCMeta):
    @abstracmethod
    def walk(self):
        pass

class WaterAnimal(metaclass=ABCMeta):
    @abstractmethod
    def swim(self):
        pass

class SkyAnimal(metaclass=ABCMeta):
    @abstractmethod
    def fly(self):
        pass

class Tiger(LandAnimal):
    def walk(self):
        print('老虎走')
  • 单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责

三、设计模式分类

  • 创建型模式(5种):工厂方法模式、抽象工厂模式、创建者模式、原型模式、单例模式
  • 结构型模式(7种):适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式
  • 行为型模式(11种):解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模板方法模式

四、创造型模式

4.1 简单工厂模式

  • 内容:不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例
  • 角色:
    • 工厂角色(Creator)
    • 抽象产品角色(Product)
    • 具体产品角色(Concrete Product)
from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta): # 抽象产品(用于限定所要调用方法)
    @abstractmethod
    def pay(self, money):
        pass

class Alipay(Payment): # 具体产品角色1
    def __init__(self, use_huabei=False):
        self.use_huabei = use_huabei

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

class WechatPay(Payment): # 具体产品角色2
    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 named %s' % method)

# client
pf = PaymentFactory
# 在强类型语言如:java中,此处的p可设置为抽象类型,即面向接口编程
p = pf.create_payment('alipay')
p.pay(100)
  • 优点:
    • 隐藏了对象创建的实现细节
    • 客户端(高层代码)不需要修改代码
  • 缺点:
    • 违反了单一职责原则,将几种创建逻辑集中到一个工厂类里(即一个工厂类要生产多个类型的产品)
    • 当添加新产品时,需要修改工厂类代码,违背了开闭原则

4.2 工厂方法模式

  • 内容:定义一个用于创建对象的接口(工厂接口)即创建了一个抽象工厂类,继承它为每一个产品创建对应的工厂子类,让子类决定实例化哪一个产品类
  • 角色:
    • 抽象工厂角色
    • 具体工厂角色
    • 抽象产品角色
    • 具体产品角色
from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta): # 抽象产品(用于限定所要调用方法)
    @abstractmethod
    def pay(self, money):
        pass

class Alipay(Payment): # 具体产品角色1
    def __init__(self, use_huabei=False):
        self.use_huabei = use_huabei

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

class WechatPay(Payment): # 具体产品角色2
    def pay(self, money):
        print("微信支付%d元." % money)

class PaymentFactory(metaclass=ABCMeta): # 抽象工厂角色
    @abstractmethod
    def create_payment(self):
        pass

class AlipayFactory(PaymentFactory): # 具体工厂角色1
    def create_payment(self):
        return Alipay()

class WechatFactory(PaymentFactory): # 具体工厂角色2
    def create_payment(self):
        return WechatPay()

class HuabeiFactory(PaymentFactory): # 具体工厂角色3
    def create_payment(self):
        return Alipay(use_huabei=True)

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

4.3 抽象工厂模式

  • 内容:定义一个工厂类接口,让工厂子类来创建一系列相关或相互依赖的对象
  • 例:生产一部手机,需要手机壳、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)

你可能感兴趣的:(Python基础(千锋篇),python,设计模式,javascript)