概念
一个软件实体如类、模块和函数应该对修改关闭,对扩展开放
理解
- 尽量减少对类文件的修改
- 通过另一个分支扩展其功能
实例
版本 1
需求
现在后台有课程小节编辑功能,打算增加一个小测验题型,并提供保存小测验的接口
方案
工厂方法:
package quizfactory
import "rabbitm/design/quizservice"
type IFactory interface {
Create() quizservice.IQuiz
}
type QuizFactory struct {
}
func (f *QuizFactory) Create() quizservice.IQuiz {
return new(quizservice.Quiz)
}
小测验接口:
package quizservice
import "fmt"
type IQuiz interface {
SaveQuiz(params map[string]string)
}
type Quiz struct {
}
func (qz *Quiz) SaveQuiz(params map[string]string) {
fmt.Println("保存小测验")
}
程序入口:
package main
import (
"rabbitm/design/quizfactory"
"rabbitm/design/quizservice"
)
var iQuiz quizservice.IQuiz
var iFactory quizfactory.IFactory
func main() {
params := make(map[string]string)
// 创建工厂
iFactory = new(quizfactory.QuizFactory)
// 创建小测验实例
iQuiz = iFactory.Create()
// 保存小测验
iQuiz.SaveQuiz(params)
}
版本 2
需求
现在小测验需要引入新题型,之前默认的是单选,现在增加多选
方案
没有考虑开闭原则,直接在具体类内修改
小测验接口:
package quizservice
import "fmt"
type IQuiz interface {
SaveQuiz(params map[string]string)
}
type Quiz struct {
}
func (qz *Quiz) SaveQuiz(params map[string]string) {
// fmt.Println("保存小测验")
if params["type"] == "单选" {
fmt.Println("保存小测验单选")
} else if params["type"] == "多选" {
fmt.Println("保存小测验多选")
}
}
结论
这种方式最容易想到,也是最好实现的,但是违反了开闭原则。如果小测验类型继续增多,会导致 SaveQuiz
方法变得臃肿难以维护
版本 3
需求
需要在方案 2 的基础上优化成符合开闭原则,对扩展开放,对修改关闭
方案
工厂方法:
package quizfactory
import "rabbitm/design/quizservice"
type IFactory interface {
Create() quizservice.IQuiz
}
type QuizFactory struct {
}
func (f *QuizFactory) Create() quizservice.IQuiz {
return new(quizservice.Quiz)
}
// 增加单选工厂
type QuizRadioFactory struct {
}
func (f *QuizRadioFactory) Create() quizservice.IQuiz {
return new(quizservice.QuizRadio)
}
// 增加多选工厂
type QuizCheckboxFactory struct {
}
func (f *QuizCheckboxFactory) Create() quizservice.IQuiz {
return new(quizservice.QuizCheckbox)
}
小测验接口:
package quizservice
import "fmt"
type IQuiz interface {
SaveQuiz(params map[string]string)
}
type Quiz struct {
}
func (qz *Quiz) SaveQuiz(params map[string]string) {
fmt.Println("保存小测验")
}
// 增加单选实现
type QuizRadio struct {
}
func (qz *QuizRadio) SaveQuiz(params map[string]string) {
fmt.Println("保存单选题")
}
// 增加多选实现
type QuizCheckbox struct {
}
func (qz *QuizCheckbox) SaveQuiz(params map[string]string) {
fmt.Println("保存多选题")
}
程序入口:
package main
import (
"rabbitm/design/quizfactory"
"rabbitm/design/quizservice"
)
var iQuiz quizservice.IQuiz
var iFactory quizfactory.IFactory
func main() {
params := make(map[string]string)
if params["type"] == "单选" {
iFactory = new(quizfactory.QuizRadioFactory)
iQuiz = iFactory.Create()
} else if params["type"] == "多选" {
iFactory = new(quizfactory.QuizCheckboxFactory)
iQuiz = iFactory.Create()
} else {
iFactory = new(quizfactory.QuizFactory)
iQuiz = iFactory.Create()
}
iQuiz.SaveQuiz(params)
}
结论
扩展了单选多选小测验,而没有修改原有的小测验代码。避免了更换维护人员和代码分支过多导致的意外
讨论区
登录评论