对象设计原则SOLID
SOLID 是面向对象设计(OOD)的核心原则,由 Robert C. Martin (Uncle Bob) 总结提出,代表了五个关键设计原则的首字母缩写。这些原则帮助开发者构建灵活、可维护、可扩展的软件系统。
SOLID 原则全景图
S
Single Responsibility
单一职责
降低耦合度
O
Open/Closed
开闭原则
提升扩展性
L
Liskov Substitution
里氏替换
确保继承安全
I
Interface Segregation
接口隔离
最小化依赖
D
Dependency Inversion
依赖倒置
解耦高层模块
单一职责原则 (SRP)
关键要点
职责隔离:每个结构体/包只承担一个核心功能领域
变更驱动:设计时思考"什么原因会导致这个结构体改变?"
命名即承诺:结构体/函数命名应清晰反映其单一职责
实施要点
// 不推荐:多个职责混合
type UserManager struct {
DB *sql.DB
}
func (m *UserManager) Create(user User) error { /* 1. 存储逻辑 */ }
func (m *UserManager) Notify(user User) error { /* 2. 通知逻辑 */ }
// 推荐:职责分离
type UserRepository struct { DB *sql.DB }
func (r *UserRepository) Save(user User) error { /* 仅存储 */ }
type UserNotifier struct { /* 邮件/短信客户端 */ }
func (n *UserNotifier) SendWelcome(user User) error { /* 仅通知 */ }
// 服务层协调
type UserService struct {
repo *UserRepository
notify *UserNotifier
}
开闭原则 (OCP)
关键要点
抽象定义契约:面向接口编程而非具体实现
扩展点设计:预留hook/策略位置支持未来功能
增量演进:新功能通过添加代码实现而非修改
实施要点
// 抽象层:定义支付接口
type PaymentProcessor interface {
Process(amount float64) error
}
// 具体实现
type CreditCardProcessor struct{}
// 新增支付方式不用修改原有代码
type CryptoProcessor struct{}
// 依赖注入保持扩展性
type OrderHandler struct {
payment PaymentProcessor
}
func NewOrderHandler(processor PaymentProcessor) *OrderHandler {
return &OrderHandler{payment: processor}
}
func (h *OrderHandler) Pay(amount float64) error {
return h.payment.Process(amount) // 支持所有实现
}
里氏替换原则 (LSP)
关键要点
行为契约一致性:确保实现符合接口预期行为
前置条件不强于:子类型输入要求不能更严格
后置条件不弱于:子类型输出承诺不能更宽松
实施要点
// 文件操作接口
type FileOperation interface {
Read() ([]byte, error)
}
// 磁盘文件实现
type DiskFile struct{}
// 内存文件实现 (必须符合接口约定)
type MemoryFile struct{}
// 测试辅助函数验证LSP
func TestFileOperations(t *testing.T) {
testCases := []FileOperation{
&DiskFile{},
&MemoryFile{},
}
for _, f := range testCases {
data, err := f.Read()
assert.NoError(t, err)
assert.True(t, len(data) > 0) // 所有实现必须满足该基础检查
}
}
接口隔离原则 (ISP)
关键要点
细粒度接口:基于功能角色划分接口
无强制依赖:客户端不被迫实现不用的方法
接口组合复用:通过组合创建复杂接口
实施要点
// 不推荐:胖接口
type DataStore interface {
Save(Data) error
Retrieve(id string) (Data, error)
Delete(id string) error
Backup() error
}
// 推荐:拆分为细粒度接口
type BasicStore interface {
Save(Data) error
Retrieve(id string) (Data, error)
}
type AdminStore interface {
Delete(id string) error
Backup() error
}
// 只实现必要接口
type UserStore struct{} // 只实现BasicStore
// 高级实现可选择组合
type SystemStore struct {
BasicStore
AdminStore
}
// 客户端按需使用
func UserFunc(store BasicStore) {
// 不需要关心Admin功能
}
依赖倒置原则 (DIP)
关键要点
解耦依赖关系:高层模块不直接依赖低层实现
抽象指向稳定:依赖抽象层保证系统健壮性
依赖注入实现:运行时动态注入具体实现
实施要点
// 数据库抽象层
type Database interface {
Query(q string) ([]Row, error)
}
// 具体实现
type MySQL struct{}
type PostgreSQL struct{}
// 高层业务模块
type ReportService struct {
db Database // 依赖抽象
}
// 构造函数注入依赖
func NewReportService(db Database) *ReportService {
return &ReportService{db: db}
}
// 使用依赖注入工具 (如google/wire)
var ServiceSet = wire.NewSet(
wire.Bind(new(Database), new(*PostgreSQL)), // 绑定接口实现
PostgreSQL.New, // 创建具体实现
NewReportService, // 注入依赖
)
// 测试替换实现
func TestReportService(t *testing.T) {
mockDB := new(MockDatabase)
service := NewReportService(mockDB) // 注入模拟对象
/* 测试逻辑 */
}
SOLID原则实施策略矩阵
SRP
功能领域划分模块
单一文件代码不超过300行
变更影响分析测试
OCP
定义稳定抽象层
是否通过新类型添加功能
新功能集成测试
LSP
行为契约文档化
接口方法输入输出约束
可替换性兼容测试
ISP
角色接口设计
接口方法数≤3个
单功能接口单元测试
DIP
依赖关系图设计
import无具体实现依赖
Mock替换测试
最后更新于