当前位置:首页>文章>设计模式>设计模式的分类与七大原则详解 | 创建型、结构型、行为型模式

设计模式的分类与七大原则详解 | 创建型、结构型、行为型模式

设计模式的分类与七大原则

一、设计模式的分类

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。


二、设计模式的七大原则

1️⃣ 开闭原则

(1) 概念

  • 定义:一个软件实体(如类、模块、函数)应该对扩展开放,对修改关闭
  • 用抽象构建框架,用实现扩展细节
  • 优点:提高软件系统的可复用性及可维护性
  • 开闭原则是所有原则的基础

(2) 开闭原则Coding

声明接口ICourse

from abc import ABC, abstractmethod

class ICourse(ABC):
    @abstractmethod
    def get_id(self):
        pass

    @abstractmethod
    def get_name(self):
        pass

    @abstractmethod
    def get_price(self):
        pass

声明接口实现类

class JavaCourse(ICourse):
    def __init__(self, course_id, name, price):
        self.id = course_id
        self.name = name
        self.price = price

    def get_id(self):
        return self.id

    def get_name(self):
        return self.name

    def get_price(self):
        return self.price

声明新的类来继承接口实现类

class JavaDiscountCourse(JavaCourse):
    def __init__(self, course_id, name, price):
        super().__init__(course_id, name, price)

    def get_discount_price(self):
        return self.get_price() * 0.8

编写测试代码

def test():
    course = JavaDiscountCourse(96, "Java开发", 348.0)
    print(f"课程ID:{course.get_id()} 课程名称:{course.get_name()} 课程原价:{course.get_price()} 课程折后价格:{course.get_discount_price()}元")

if __name__ == "__main__":
    test()

2️⃣ 依赖倒置原则

(1) 概念

  • 定义:高层模块不应该依赖于低层模块,两者都应该依赖于抽象
  • 抽象不应该依赖细节,细节应该依赖抽象
  • 针对接口编程,不要针对实现编程
  • 优点:可以降低类间的耦合性,提高系统稳定性,提高代码可读性和可维护性,可降低修改程序所造成的风险

(2) 依赖倒置原则Coding

声明接口

from abc import ABC, abstractmethod

class ICourse(ABC):
    @abstractmethod
    def study_course(self):
        pass

创建多个实现类(JavaCourse、FECourse、PythonCourse)

class JavaCourse(ICourse):
    def study_course(self):
        print("学生在学习Java课程")
class FECourse(ICourse):
    def study_course(self):
        print("学生在学习FE课程")
class PythonCourse(ICourse):
    def study_course(self):
        print("学生在学习Python课程")

编写学生类

class Student:
    def __init__(self):
        self.course = None

    # 开放set方法实现注入
    def set_course(self, course):
        self.course = course

    # 核心方法
    def study_course(self):
        self.course.study_course()

编写测试方法

def test():
    student = Student()

    student.set_course(JavaCourse())
    student.study_course()

    student.set_course(FECourse())
    student.study_course()

if __name__ == "__main__":
    test()

3️⃣ 单一职责原则

(1) 概念

  • 定义:不要存在多于一个导致类变更的原因
  • 一个类、接口、方法只负责一项职责
  • 降低类的复杂性,提高类的可读性,提高系统的可维护性,降低变更引起的风险

(2) 单一职责原则Coding

创建获取课程内容的接口和管理课程的接口

# 获取课程内容接口
from abc import ABC, abstractmethod

class ICourseContent(ABC):
    @abstractmethod
    def get_course_name(self):
        pass

    @abstractmethod
    def get_course_video(self):
        pass
# 课程管理接口
class ICourseManager(ABC):
    @abstractmethod
    def study_course(self):
        pass

    @abstractmethod
    def refund_course(self):
        pass

创建实现类实现两个接口

class CourseImpl(ICourseManager, ICourseContent):
    def study_course(self):
        pass

    def refund_course(self):
        pass

    def get_course_name(self):
        return None

    def get_course_video(self):
        return bytes()

④ 其实也可以通过类来实现单一职责的设计,但是使用类来实现单一职责如果控制不当会使类的数量爆炸,所以不推荐使用类来实现单一职责推荐使用接口来实现,毕竟类对于接口是可以多实现的嘛,也比较容易扩展。


4️⃣ 接口隔离原则

(1) 概念

  • 定义:用多个专门的接口,而不使用单一的总接口,客户端不应该依赖于不需要的接口
  • 一个类对一个类的依赖,应该建立在最小的接口上
  • 建立单一接口,不要建立庞大臃肿的接口
  • 尽量细化接口,接口中的方法尽量少
  • 在使用接口隔离原则的时候一定要适度(如果控制不好,会提升程序的复杂性)
  • 优点:符合高内聚、低耦合的设计思想,从而使得类具有很好的可读性、可扩展性和可维护性

(2) 接口隔离原则Coding

创建多个不同的接口

from abc import ABC, abstractmethod

class IEatAnimalAction(ABC):
    @abstractmethod
    def eat(self):
        pass
class IFlyAnimalAction(ABC):
    @abstractmethod
    def fly(self):
        pass
class ISwimAnimalAction(ABC):
    @abstractmethod
    def swim(self):
        pass

创建具体的实现类通过细粒度的实现组合来实现接口

class Dog(ISwimAnimalAction, IEatAnimalAction):
    def eat(self):
        pass

    def swim(self):
        pass

接口隔离原则与单一职责原则的区别

单一职责原则:强调的是接口、类、方法的职责是单一的,这里强调的是职责,也就是说在一个接口中只要职责是单一的有多个方法也可以(例如游泳、仰泳、自由泳等);另外单一职责原则约束是对接口、类、方法的约束针对的是程序中的实现和细节。

接口隔离原则:注重的是对接口依赖的隔离,针对的是对程序框架的构建。


5️⃣ 迪米特原则(最少知道原则)

(1) 概念

  • 定义:一个对象应该对其他对象保持最少的了解,又叫最少知道原则
  • 尽量降低类与类之间的耦合
  • 优点:降低类之间的耦合
  • 强调只和朋友交流,不和陌生人说话
  • 朋友:出现在成员变量、方法的输入、输出参数中的类称为成员朋友类,而出现在方法体内部的类不属于朋友类

(2) 迪米特原则Coding

创建Boss对象

class Boss:
    def command_check_number(self, team_leader):
        team_leader.check_number_of_courses()

创建Boss的"朋友"TeamLeader

class TeamLeader:
    def check_number_of_courses(self):
        course_list = []
        for i in range(20):
            course_list.append(Course())
        print(f"在线课程的数量是:{len(course_list)}")

创建TeamLeader的朋友Course

class Course:
    pass

编写测试类

def test():
    boss = Boss()
    team_leader = TeamLeader()
    boss.command_check_number(team_leader)

if __name__ == "__main__":
    test()

6️⃣ 里氏替换原则

(1) 概念

  • 定义:如果对每一个类型为T1的对象O1,都有类型为T2的对象O2,使得以T1定义的所有程序P在所有的对象O1都替换成O2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。
  • 定义扩展:一个软件实体如果适用一个父类的话,那一定适用于其子类,所有引用父类的地方必须能透明的使用其子类的对象,子类对象能够替换父类对象,而程序逻辑不变。
  • 引申意义:子类可以扩展父类的功能,但不能改变父类原有的功能
  • 含义1:子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
  • 含义2:子类中可以增加自己特有的方法
  • 含义3:当子类的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类方法的输入参数更宽松
  • 含义4:当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的输出/返回值)要比父类更严格或相等
  • 优点1:约束继承泛滥,开闭原则的一种体现
  • 优点2:加强程序的健壮性,同时变更时也可以做到非常好的兼容性提高程序的维护性和扩展性,降低需求变更时引入的风险

(2) 里氏替换原则Coding

由于里氏替换原则定义比较多,这里我们仅以含义3为参照来进行Coding,其他含义大家可以对照着文字解释进行尝试;在实际的工作中大家可以根据实际的环境来尽量满足里氏替换原则。

定义Base类

class Base:
    def method(self, data):
        print("父类被执行")

定义Child来实现Base

class Child(Base):
    def method(self, data):
        print("子类方法被执行")

编写测试类

def test():
    child = Child()
    data = {"key": "value"}
    child.method(data)

if __name__ == "__main__":
    test()

7️⃣ 合成复用原则

(1) 概念

  • 定义:尽量使用对象组合/聚合,而不是继承关系达到软件复用的目的(聚合has-A和组合contains-A)
  • 优点:可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少

(2) 合成复用原则Coding

创建抽象基类

from abc import ABC, abstractmethod

class DBConnection(ABC):
    @abstractmethod
    def get_connection(self):
        pass

创建实现类来继承抽象基类

class MySQLConnection(DBConnection):
    def get_connection(self):
        return "MySQL数据库连接"
class PostgreSQLConnection(DBConnection):
    def get_connection(self):
        return "PostgreSQL数据库连接"

创建业务应用

class ProductDao:
    def __init__(self):
        self.db_connection = None

    def set_db_connection(self, db_connection):
        self.db_connection = db_connection

    def add_product(self):
        conn = self.db_connection.get_connection()
        print(f"使用{conn}增加产品")

创建测试类

def test():
    product_dao = ProductDao()
    product_dao.set_db_connection(PostgreSQLConnection())
    product_dao.add_product()

if __name__ == "__main__":
    test()

合成复用原则是满足开闭原则以及里氏替换原则的。

您已阅读完《设计模式(共2篇)》专题的第 1 篇。请继续阅读该专题下面的文章:

数据结构

Python集合Set实现详解:二分搜索树vs链表性能对比 | 数据结构教程

2025-8-16 21:25:12

设计模式

设计模式:工厂模式详解(Python版)

2025-8-29 10:23:46

搜索