接口粒度把控原则
- 单一职责原则:接口应该只做一件事,每个接口的方法应该紧密围绕一个特定的功能或行为。例如,一个处理文件读取的接口
FileReader
应该只包含读取文件相关的方法,如 Read
。
- 避免过度抽象:不要为了抽象而抽象,接口中的方法应该具有实际意义,且能被多种不同类型实现。例如,定义一个通用的
DoSomething
方法而不明确其具体功能,这是不合理的。
细粒度接口
- 应用场景:适用于需要高度灵活性和复用性的场景。例如在一个图形绘制库中,可能有
Drawable
接口定义基本绘制方法,Movable
接口定义移动方法。一个 Circle
结构体可以同时实现 Drawable
和 Movable
接口,这样在不同场景下,如只需要绘制时,可以只关注 Drawable
接口,而在需要移动图形时,关注 Movable
接口。
- 优点:
- 灵活性高:可以根据需求组合不同的细粒度接口,实现多样化的功能。
- 复用性强:细粒度接口可以被多个不同类型复用,提高代码复用率。
- 缺点:
- 接口数量多:可能导致接口数量膨胀,增加代码管理和理解成本。
- 调用复杂:调用方可能需要实现多个接口,增加使用难度。
// 细粒度接口示例
type Drawable interface {
Draw()
}
type Movable interface {
Move(x, y int)
}
type Circle struct {
X, Y int
}
func (c Circle) Draw() {
// 绘制逻辑
}
func (c *Circle) Move(x, y int) {
c.X = x
c.Y = y
}
粗粒度接口
- 应用场景:当功能相关性强且需要整体操作时使用。比如一个用户管理系统,有一个
UserManager
接口,包含用户的增删改查等一系列方法。
- 优点:
- 简单易用:调用方只需要实现一个粗粒度接口,使用方便。
- 逻辑清晰:对于功能相对集中的场景,粗粒度接口能更好地体现整体逻辑。
- 缺点:
- 灵活性差:如果只需要部分功能,也必须实现整个接口,造成代码冗余。
- 复用性低:由于接口功能过于具体,复用性不如细粒度接口。
// 粗粒度接口示例
type UserManager interface {
CreateUser(user User)
DeleteUser(id string)
UpdateUser(user User)
GetUser(id string) User
}
type User struct {
ID string
Name string
}
type DefaultUserManager struct{}
func (dm DefaultUserManager) CreateUser(user User) {
// 创建用户逻辑
}
func (dm DefaultUserManager) DeleteUser(id string) {
// 删除用户逻辑
}
func (dm DefaultUserManager) UpdateUser(user User) {
// 更新用户逻辑
}
func (dm DefaultUserManager) GetUser(id string) User {
// 获取用户逻辑
return User{}
}