写在前面
关于面相对象和五大基本原则其实在我们开发过程中已经有意无意的遵循了,只不过很多时候没有这个概念。今天就简单完整梳理一下面相对象和五大基本原则在go中的体现。
面相对象特点:
1、封装
type animal struct {
food string
}
// NewAnimal 构造函数,用于创建 animal 实例
func NewAnimal(food string) *animal {
return &animal{
food: food,
}
}
// GetFood 返回 food 属性
func (a *animal) GetFood() string {
return a.food
}
// SetFood 设置 food 属性
func (a *animal) SetFood(food string) {
a.food = food
}
2、继承
go 语言中并没有继承和多态,但是可以实现类似效果
type Dog struct {
animal // 模拟继承
}
func NewDog(food string) *Dog {
return &Dog{
animal: animal{food: food},
}
}
// Eat 实现 AnimalBehavior 接口
func (d *Dog) Eat() {
println("狗吃:" + d.GetFood())
}
// Bark 特有方法
func (d *Dog) Bark() {
println("汪汪叫")
}
type Cat struct {
animal // 模拟继承
}
func NewCat(food string) *Cat {
return &Cat{
animal: animal{food: food},
}
}
// Eat 实现 AnimalBehavior 接口
func (c *Cat) Eat() {
println("猫吃:" + c.GetFood())
}
// Meow 特有方法
func (c *Cat) Meow() {
println("喵喵叫")
}
3、多态
// IAnimal 定义动物的行为接口(多态)
type IAnimal interface {
Eat()
}
// Feed 实现多态
func Feed(animal IAnimal) {
animal.Eat()
}
func main() {
dog := NewDog("骨头")
cat := NewCat("鱼")
Feed(dog) // 多态调用
Feed(cat) // 多态调用
dog.Bark() // 调用特有方法
cat.Meow() // 调用特有方法
}
五大原则
- 单一职责:一个类(或结构体、函数等)应该只有一个引起它变化的原因,即只负责一项职责
代码中体现: -animal 结构体仅封装动物的基础属性(food)。 -每个方法如 GetFood()、SetFood() 只完成单一功能。 -Dog 和 Cat 分别实现自己的行为逻辑。 -接口 IAnimal 抽象出“吃”的行为,不涉及其他逻辑。 -函数 Feed 只负责调用接口的 Eat() 方法。
- 开闭原则:软件实体(类、模块、函数等)应对扩展开放,对修改关闭。
代码中的体现: -使用了接口 IAnimal 定义通用行为 Eat()。 -当需要新增动物类型时(如 Bird),只需定义新结构体并实现 Eat() 方法即可,无需修改现有 Feed 函数或其他已有代码。
- 里氏替换:所有引用基类的地方必须能透明地使用其子类的对象。
代码中的体现: -使用了接口 IAnimal 定义通用行为 Eat()。 -当需要新增动物类型时(如 Bird),只需定义新结构体并实现 Eat() 方法即可,无需修改现有 Feed 函数或其他已有代码。
- 接口隔离:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应建立在最小的接口上。
代码中的体现: -Dog 和 Cat 都实现了 IAnimal 接口。 -Feed 函数接收的是 IAnimal 接口类型,传入 Dog 或 Cat 实例均可正常运行。 -子类可以替代接口被使用,且行为正确。
- 依赖倒置:高层模块不应该依赖低层模块,二者都应该依赖于抽象(接口)。抽象不应依赖细节,细节应依赖抽象。
代码中的体现: -IAnimal 接口仅定义了一个方法 Eat()。 -如果将来有动物不需要吃东西,则不会强制实现该接口。