第一章:Python设计模式概述
设计模式是软件开发中针对常见问题的可重用解决方案,它们不依赖于具体语言,但在 Python 中因其动态特性和简洁语法而展现出独特优势。掌握设计模式有助于提升代码的可维护性、可扩展性和可读性。设计模式的三大分类
- 创建型模式:关注对象的创建机制,如单例模式、工厂模式。
- 结构型模式:处理类或对象的组合,如适配器模式、装饰器模式。
- 行为型模式:定义对象间的通信方式,如观察者模式、策略模式。
Python中的单例模式实现
单例模式确保一个类只有一个实例,并提供全局访问点。在 Python 中可通过重写__new__ 方法实现:
class Singleton:
_instance = None # 存储唯一实例
def __new__(cls):
if cls._instance is None:
# 仅在实例不存在时创建
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
# 使用示例
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # 输出: True,证明为同一实例
常用设计模式对比
| 模式名称 | 适用场景 | 优点 |
|---|---|---|
| 工厂模式 | 对象创建逻辑复杂时 | 解耦创建与使用 |
| 装饰器模式 | 动态添加功能 | 避免继承爆炸 |
| 观察者模式 | 事件通知系统 | 实现松耦合通信 |
graph TD
A[客户端] --> B(调用工厂)
B --> C{创建对象}
C --> D[具体产品A]
C --> E[具体产品B]
第二章:创建型设计模式详解
2.1 单例模式:确保类的唯一实例
单例模式是一种创建型设计模式,用于确保一个类在整个应用程序生命周期中仅存在一个实例,并提供一个全局访问点。实现原理
通过私有化构造函数防止外部直接实例化,同时在类内部持有一个静态实例引用,并提供公共静态方法获取该实例。package singleton
import "sync"
type Singleton struct{}
var (
instance *Singleton
once sync.Once
)
func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{}
})
return instance
}
上述 Go 语言代码使用 sync.Once 确保并发安全的单例初始化。其中 once.Do() 保证初始化逻辑仅执行一次,instance 为私有变量,避免外部修改。
典型应用场景
- 配置管理器
- 日志记录器
- 数据库连接池
2.2 工厂方法模式:定义创建对象的接口
工厂方法模式是一种创建型设计模式,它定义了一个创建对象的接口,但由子类决定实例化哪个类。该模式将对象的创建延迟到子类中实现,从而提升系统的可扩展性与解耦程度。核心结构
主要包含四个角色:- Product:定义产品接口
- ConcreteProduct:具体产品实现
- Creator:声明工厂方法
- ConcreteCreator:实现工厂方法以返回具体产品
代码示例
type Product interface {
GetName() string
}
type ConcreteProductA struct{}
func (p *ConcreteProductA) GetName() string {
return "Product A"
}
type Creator interface {
FactoryMethod() Product
}
type ConcreteCreatorA struct{}
func (c *ConcreteCreatorA) FactoryMethod() Product {
return &ConcreteProductA{}
}
上述代码中,Creator 接口定义了 FactoryMethod(),返回一个 Product 类型。具体创建逻辑由 ConcreteCreatorA 实现,调用时无需了解具体产品类型,仅依赖抽象接口即可完成对象构建,增强了模块间的松耦合性。
2.3 抽象工厂模式:创建一系列相关对象
抽象工厂模式用于创建一组相关或依赖对象的家族,而无需指定具体类。它通过定义一个创建产品族的接口,使得客户端与具体实现解耦。核心结构
- 抽象工厂(Abstract Factory):声明创建一系列产品的方法
- 具体工厂(Concrete Factory):实现创建具体产品族的逻辑
- 抽象产品(Abstract Product):定义产品的接口
- 具体产品(Concrete Product):工厂创建的实际对象
代码示例
type GUIFactory interface {
CreateButton() Button
CreateCheckbox() Checkbox
}
type WindowsFactory struct{}
func (f *WindowsFactory) CreateButton() Button {
return &WindowsButton{}
}
func (f *WindowsFactory) CreateCheckbox() Checkbox {
return &WindowsCheckbox{}
}
上述代码定义了一个 GUI 抽象工厂,可生成按钮和复选框。WindowsFactory 实现该接口,返回 Windows 风格的具体控件。客户端通过工厂接口编程,无需关心对象创建细节,便于扩展新主题(如 macOS 工厂)。
2.4 建造者模式:分步构建复杂对象
核心思想与适用场景
建造者模式用于将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。它适用于包含多个组成部分的复杂对象,且构造过程步骤稳定但参数多变。- 避免构造函数参数爆炸
- 提升代码可读性和可维护性
- 支持不可变对象的逐步构建
Go语言实现示例
type Computer struct {
CPU, GPU string
RAMSize int
}
type ComputerBuilder struct {
computer Computer
}
func (b *ComputerBuilder) SetCPU(cpu string) *ComputerBuilder {
b.computer.CPU = cpu
return b
}
func (b *ComputerBuilder) SetGPU(gpu string) *ComputerBuilder {
b.computer.GPU = gpu
return b
}
func (b *ComputerBuilder) SetRAM(ram int) *ComputerBuilder {
b.computer.RAMSize = ram
return b
}
func (b *ComputerBuilder) Build() Computer {
return b.computer
}
上述代码通过链式调用逐步设置属性,最终调用 Build() 返回完整对象。每个设置方法返回构建器自身,便于连续调用。该方式清晰表达了构建流程,避免了冗长的构造函数,并支持灵活扩展。
2.5 原型模式:通过克隆提高创建效率
在对象创建成本较高的场景中,原型模式通过复制现有实例来避免重复初始化过程,显著提升性能。该模式的核心是定义一个克隆接口,使对象能自我复制。克隆机制实现
type Prototype interface {
Clone() Prototype
}
type ConcretePrototype struct {
Data []int
}
func (p *ConcretePrototype) Clone() Prototype {
copy := *p
copy.Data = make([]int, len(p.Data))
copy(copy.Data, p.Data)
return ©
}
上述代码中,Clone() 方法复制结构体并深拷贝引用类型字段,确保原始对象与克隆对象互不影响。
使用优势
- 避免重复执行复杂构造逻辑
- 运行时动态加载和复制对象
- 简化对象创建接口
第三章:结构型设计模式解析
3.1 适配器模式:兼容不匹配的接口
适配器模式用于解决接口不兼容的问题,通过封装一个类的接口,使其与另一个期望的接口匹配。它常用于集成第三方库或遗留系统。基本结构
适配器模式包含三个核心角色:目标接口(Target)、被适配者(Adaptee)和适配器(Adapter)。适配器将Adaptee的接口转换为客户端期望的Target接口。代码示例
type Target interface {
Request() string
}
type Adaptee struct{}
func (a *Adaptee) SpecificRequest() string {
return "Adaptee method"
}
type Adapter struct {
adaptee *Adaptee
}
func (ad *Adapter) Request() string {
return ad.adaptee.SpecificRequest()
}
上述代码中,Adaptee 提供了特定方法,但接口不匹配。适配器 Adapter 实现了 Target 接口,并在内部调用 Adaptee 的方法,完成接口转换。
3.2 装饰器模式:动态添加功能特性
装饰器模式是一种结构型设计模式,允许在不修改原有对象逻辑的前提下,动态地为其添加新的功能。它通过组合的方式,将功能分散到独立的装饰类中,实现关注点分离。核心思想
装饰器模式依赖于抽象组件接口,具体组件和装饰器均实现该接口。多个装饰器可层层嵌套,形成责任链式调用。代码示例
type Component interface {
Operation() string
}
type ConcreteComponent struct{}
func (c *ConcreteComponent) Operation() string {
return "Basic operation"
}
type Decorator struct {
component Component
}
func (d *Decorator) Operation() string {
return "Enhanced: " + d.component.Operation()
}
上述代码中,Decorator 持有一个 Component 接口实例,可在调用前后插入额外逻辑。通过组合而非继承扩展行为,提升了灵活性与可维护性。
应用场景
- 日志记录、权限校验等横切关注点
- 中间件系统中的请求处理链
- GUI组件的功能增强
3.3 代理模式:控制对象的访问方式
代理模式是一种结构型设计模式,用于为其他对象提供一种间接访问机制,在不改变原始类的前提下增强或控制其行为。核心结构与角色
代理模式包含三个关键角色:- Subject(抽象主题):定义真实对象和代理对象的公共接口;
- RealSubject(真实主题):具体业务逻辑的执行者;
- Proxy(代理):持有真实对象的引用,可附加访问控制、延迟加载等逻辑。
代码示例:Go 中的虚拟代理实现
type Image interface {
Display()
}
type RealImage struct {
filename string
}
func (r *RealImage) LoadFromDisk() {
fmt.Printf("Loading %s from disk\n", r.filename)
}
func (r *RealImage) Display() {
fmt.Printf("Displaying %s\n", r.filename)
}
type ProxyImage struct {
realImage *RealImage
filename string
}
func (p *ProxyImage) Display() {
if p.realImage == nil {
p.realImage = &RealImage{filename: p.filename}
p.realImage.LoadFromDisk()
}
p.realImage.Display()
}
上述代码中,ProxyImage 延迟创建 RealImage 实例,仅在真正需要时才加载资源,有效优化性能。代理对象封装了创建逻辑,调用方无需感知内部延迟加载机制。
第四章:行为型设计模式实战
4.1 观察者模式:实现事件订阅机制
观察者模式是一种行为设计模式,允许你定义一个订阅机制,使多个观察者对象监听某个主题对象的状态变化。当主题状态发生变化时,所有注册的观察者都会自动收到通知。核心结构与角色
- Subject(主题):维护观察者列表,提供注册与注销接口。
- Observer(观察者):定义接收更新通知的接口。
- ConcreteObserver:实现具体的通知处理逻辑。
代码实现示例
type Subject struct {
observers []func(string)
}
func (s *Subject) Subscribe(observer func(string)) {
s.observers = append(s.observers, observer)
}
func (s *Subject) Notify(event string) {
for _, obs := range s.observers {
obs(event)
}
}
上述 Go 示例中,Subscribe 方法用于添加监听函数,Notify 遍历所有监听者并传递事件数据,实现松耦合的事件通信机制。
4.2 策略模式:封装可互换的算法族
策略模式用于将一组可互换的算法封装在独立的类中,使它们可以动态切换,而无需修改客户端逻辑。该模式的核心是定义统一的策略接口,各个具体策略实现该接口。核心结构
- Strategy 接口:声明算法的公共操作;
- ConcreteStrategy:实现具体算法;
- Context:持有策略实例并委托执行。
代码示例(Go)
type PaymentStrategy interface {
Pay(amount float64) string
}
type CreditCardStrategy struct{}
func (c *CreditCardStrategy) Pay(amount float64) string {
return fmt.Sprintf("Paid %.2f via Credit Card", amount)
}
type PayPalStrategy struct{}
func (p *PayPalStrategy) Pay(amount float64) string {
return fmt.Sprintf("Paid %.2f via PayPal", amount)
type PaymentContext struct {
strategy PaymentStrategy
}
func (p *PaymentContext) SetStrategy(s PaymentStrategy) {
p.strategy = s
}
func (p *PaymentContext) ExecutePayment(amount float64) string {
return p.strategy.Pay(amount)
}
上述代码中,PaymentStrategy 定义了支付行为的统一接口,CreditCardStrategy 和 PayPalStrategy 提供不同实现。通过 PaymentContext 动态设置策略,实现解耦。
4.3 命令模式:将请求封装为对象
命令模式是一种行为设计模式,它将请求封装成独立的对象,从而使你可以用不同的请求、队列或日志来参数化其他对象。核心结构与角色
- Command:声明执行操作的接口
- ConcreteCommand:实现具体请求的执行逻辑
- Invoker:调用命令对象执行请求
- Receiver:真正执行请求的对象
代码示例
type Command interface {
Execute()
}
type LightOnCommand struct {
light *Light
}
func (c *LightOnCommand) Execute() {
c.light.TurnOn()
}
上述代码定义了一个打开灯的命令。LightOnCommand 持有对 Light(接收者)的引用,并在 Execute 方法中调用其行为。通过将“开灯”这一动作封装为对象,可以在运行时动态传递、撤销或记录该请求,提升了系统的灵活性与解耦程度。
4.4 模板方法模式:定义算法骨架结构
模板方法模式属于行为型设计模式,它在抽象类中定义一个算法的骨架,将部分步骤延迟到子类中实现。该模式通过继承实现代码复用,同时保持算法结构不变。核心结构与角色
- 抽象类(AbstractClass):定义算法的模板方法及抽象操作
- 具体类(ConcreteClass):实现抽象类中的具体步骤
代码示例
abstract class DataProcessor {
// 模板方法,定义算法骨架
public final void process() {
readData();
parseData();
validateData();
saveData();
}
abstract void readData();
abstract void parseData();
// 钩子方法,可选覆盖
boolean validateData() { return true; }
void saveData() {
System.out.println("Saving data...");
}
}
上述代码中,process() 方法为模板方法,封装了固定的数据处理流程。子类只需实现 readData() 和 parseData(),无需改变整体执行逻辑,从而实现算法结构的统一与行为的灵活扩展。
第五章:设计模式综合应用与最佳实践
构建可扩展的支付系统
在现代电商平台中,支付模块需支持多种渠道(如支付宝、微信、银联)。结合策略模式与工厂模式可实现灵活扩展:
type PaymentStrategy interface {
Pay(amount float64) string
}
type Alipay struct{}
func (a *Alipay) Pay(amount float64) string {
return fmt.Sprintf("支付宝支付 %.2f 元", amount)
}
type PaymentFactory struct{}
func (f *PaymentFactory) GetPayment(method string) PaymentStrategy {
switch method {
case "alipay":
return &Alipay{}
case "wechat":
return &WechatPay{}
default:
panic("不支持的支付方式")
}
}
日志系统的观察者与单例组合
日志模块通常作为全局服务存在,使用单例确保唯一实例,同时通过观察者模式通知多个处理器(如文件、数据库、远程服务):- Logger 单例维护订阅者列表
- 每当日志事件触发,调用所有 Observer 的 Update 方法
- FileLogger 和 AlertLogger 可独立处理不同级别日志
微服务中的模式协同
在订单服务中,使用模板方法定义创建流程,钩子方法允许子类定制库存扣减与积分计算逻辑。配合依赖注入容器管理各策略实例,提升测试性与解耦程度。| 模式 | 用途 | 优势 |
|---|---|---|
| 策略 + 工厂 | 支付方式动态切换 | 新增渠道无需修改核心逻辑 |
| 观察者 + 单例 | 日志分发 | 多目标异步处理 |
用户请求 → 工厂创建策略 → 执行对应支付 → 日志发布事件 → 多个监听器响应
3673

被折叠的 条评论
为什么被折叠?



