前言

一些开源的第三方库、框架中大量采用设计模式设计底层代码,使得框架的使用者,可以更加简单、舒服地调用底层代码进行高层代码的开发;

这就是设计模式的魅力所在;

软件开发流程大致分为以下3大流程

  • 需求分析
  • 程序分析和设计
  • 程序开发

设计模式本质是针对面向对象编程,在程序设计阶段应当遵守的设计原则。

什么是好用的代码呢?其实就是代码质量比较高,如何评价代码质量的高低呢?最常用的、最重要的评价标准,就是代码的

遵守这些设计原则,有利于设计出更加松耦合、易于扩展、易于高层代码调用的程序;

一、设计模式概念

设计模式(Design Pattern)是前辈们经过相当长的一段时间的试验和错误总结出来的,是软件开发过程中面临的通用问题的解决方案。

这些解决方案使用设计模式是为了提高代码的

  • 可维护性
  • 可读性
  • 可扩展性
  • 灵活性
  • 简洁性
  • 可复用性
  • 可测试性

每1个设计模式系统地命名、解释和评价了面向对象系统中1个重要的反复出现的设计。

二、面向对象

上文提到设计模式是针对面向对象程序提出的程序设计方案,所以回顾下面向对象知识。

1.面向对象的3大特性

面向对象的3大特性不是1个平级并列的关系而是1个循序递进的关系

封装

把属性(数据)、方法(函数)封装到1个类里面

继承

通过继承可以解决2个类之间复用代码的问题

多态

Python本身是1本多态的语言

2.面向对象的接口

在面向对象编程中我们经常使用接口

接口概念

接口是若干抽象方法的集合

接口作用

规范、限制实现类的方法

对高层代码(Client)隐藏了类的内部实现

降低高层代码(Client)调用底层代码的复杂度(Client底层代码的调用者不需要关心底层代码是怎么实现的,达到目的即可)

三、面向对象设计原则

SOLID原则指:面向对象编程需要遵循的5大原则

5大原则英文首字母拼成Solid单词;

1.单一职责(Single Responsibility Principle)

不要存在 >1个导致类变更的原因,一旦上层代码修改,只能有1个理由去修改底层代码的1个类代码。

既1个类负责1项职责。

不能把不同类型的代码都集中在1个类里面,这样设计一旦高层代码修改,就大大提高了这个类的代码修改风险;

2.开放封闭原则(Open Close Principle)

1个软件实体(如类、模块、函数)应该对扩展开放,对修改关闭。

既软件扩展新功能时应尽量不修改原代码。

3.里氏替换原则(Liskov Substitution Principle)

所有引用父类的地方必须能透明地使用其子类对象;

即在调用1个类的方法时,这个方法的参数,可以是1个父类的对象,也可以是继承了这个父类的子类的对象;

这就需要子类在重写方法和父类的方法时,实现的行为应当和父类方法保持一致;

子类和父类方法的逻辑可以不一致,但是传入参数、返回的返回值一致;

4.接口隔离原则(Interface Segregation Principle)

使用多个专门的接口,而不使用单一的总接口。

客户端即高层代码也就是低层代码的调用者,客户端不应该依赖哪些它不需要的接口。

from abc import ABC, abstractmethod

# 动物接口-存在设计缺陷
# class Animal(ABC):
#     @abstractmethod
#     def walk(self):
#         pass
#
#     @abstractmethod
#     def swim(self):
#         pass
#
#     @abstractmethod
#     def fly(self):
#         pass


# # ---------------高层代码
# # 具体动物类-青蛙
# # Class Tiger must implement all abstract methods
# class Frog(Animal):
#     def swim(self):
#         print("青蛙水里游~")
#
#
# # 具体动物类-老虎
# # Class Tiger must implement all abstract methods
# class Tiger(Animal):
#     def walk(self):
#         print("老虎地上走")


# 具体动物类-青蛙
# # Class Tiger must implement all abstract methods
# class Swan(Animal):
#     def fly(self):
#         print("天鹅天上飞~")


# 修复Animal单一接口设计缺陷
"""
使用多个专门接口
不使用单一接口
这样客户端不依赖哪些它不需要的接口
"""


class LandAnimal(ABC):
    @abstractmethod
    def walk(self):
        pass


class WaterAnimal(ABC):
    @abstractmethod
    def swim(self):
        pass


class FlyAnimal(ABC):
    @abstractmethod
    def fly(self):
        pass


# ---------------高层代码
# 具体动物类-老虎
class Tiger(LandAnimal):
    def walk(self):
        print("老虎地上走")


# 具体动物类-青蛙
class Frog(LandAnimal, WaterAnimal):
    def walk(self):
        print("青蛙水里游~")

    def swim(self):
        print("青蛙地上走~")


# 具体动物类-青蛙
class Swan(LandAnimal, WaterAnimal, FlyAnimal):
    def fly(self):
        print("天鹅天上飞~")

    def walk(self):
        print("天鹅天地上走~")

    def swim(self):
        print("天鹅天水中游~")


if __name__ == '__main__':
    a1 = Tiger()
    a1.walk()
    a2 = Frog()
    a2.walk()
    a2.swim()
    a3 = Swan()
    a3.walk()
    a3.swim()
    a3.fly()
接口拆分

5.依赖倒置原则(Dependency Inversion Principle)

高层模块不应该依赖地层模块,二者都应该依赖其约定的接口。

接口的设计原则不应该依赖代码细节,代码细节应该依赖接口。即先定义接口,方法里面的逻辑根据接口约定实现。

针对接口编程,而不是针对实现编程

面向接口编程的好处就是低层代码一旦修改,调用低层代码的高层代码,不需要修改;

因为双方都遵循约定的接口,约定包括:调用底层代码的方法的名称、入参、返回值

底层代码需要修改不能修改接口中定义的内容,而是修改方法里面的代码逻辑。

四、设计模式分类

设计模式本质是针对面向对象编程而提出的设计准则。

设计模式共计23个,分为3大类。

可创建型(Creational):创建型模式主要用于创建对象

结构型(Structural):结构型模式主要用于处理类或对象的组合进行协同工作

行为型(Behavioral):行为型模式主要用于描述类或对象的行为即方法,类或对象应怎样交互?怎样分配职责?

由于篇幅原因,我把23个设计模式拆分为23篇文章, 逐一讲解;

1.创建型模式

创建型模式:主要聚焦在在隐藏底层代码的前提下,如何创建1个对象?分为5个子类。

工厂方法模式

抽象工厂模式

构造者模式

原型模式

单例模式

2.结构型模式

结构型模式:主要聚焦在 多个类之间应该组织成1种什么结构?才能一起协同工作,分为7个子类。

适配器模式

桥模式

组合模式

装饰模式

外观模式

享元模式

代理模式

3.行为型模式

行为型模式:主要聚焦在类中的方法,如何通过方法完成各某种行为,分为11个子类。

责任链模式

命令模式

迭代器模式

中介者解释器模式

备忘录模式

观察者模式

状态模式

策略模式

访问者模式

模板方法模式

 

 

 

参考

posted on 2024-02-03 12:04  Martin8866  阅读(9)  评论(0编辑  收藏  举报