Go语言实践开闭原则非侵入式设计与装饰器模式
· 阅读需 3 分钟
1. 开闭原则(Open-Closed Principle, OCP)
开闭原则的核心思想是软件实体(如类、模块、函数等)应该对扩展开放,对修改封闭。这意味着一个实体允许其行为被扩展,但是不应当修改其源代码。
Go 代码示例
假设我们有一个日志系统,需要支持不同格式的日志输出(如 JSON、XML 等)。我们可以定义一个日志接口,然后为每种日志格式提供一个实现。这样,如果将来需要支持新的日志格式,我们只需添加新的实现,而不需修改现有代码。
package main
import (
"fmt"
"encoding/json"
"encoding/xml"
)
// Logger 是对日志操作的抽象
type Logger interface {
Log(message string) error
}
// JSONLogger 是输出JSON格式日志的实现
type JSONLogger struct{}
func (l *JSONLogger) Log(message string) error {
data, err := json.Marshal(struct{Message string}{Message: message})
if err != nil {
return err
}
fmt.Println(string(data))
return nil
}
// XMLLogger 是输出XML格式日志的实现
type XMLLogger struct{}
func (l *XMLLogger) Log(message string) error {
data, err := xml.Marshal(struct{Message string}{Message: message})
if err != nil {
return err
}
fmt.Println(string(data))
return nil
}
func main() {
var logger Logger
// 使用JSONLogger
logger = &JSONLogger{}
logger.Log("Hello JSON")
// 使用XMLLogger
logger = &XMLLogger{}
logger.Log("Hello XML")
}
2. 非侵入式设计
非侵入式设计指的是在添加或修改功能时,尽量不修改现有的代码结构,而是通过扩展等方式来增强功能。这样可以最大限度地保持原有代码的稳定性和可用性。
在上述日志系统的例子中,我们通过实现Logger
接口来添加新的日志格式,而不是修改Logger
接口或其他已有实现。这种方式就是典型的非侵入式设计。
3. 装饰器模式
装饰器模式是一种设计模式,允许向一个现有的对象添加新的功能,同时又不改变其结构。这是一种实现开闭原则的有效手段。
Go 代码示例
如果我们想要为日志添加时间戳功能,可以创建一个装饰器来实现这一需求,而不是修改现有的日志实现。
import (
"time"
)
// TimestampLogger 是装饰器,为日志添加时间戳
type TimestampLogger struct {
Logger Logger
}
func (l *TimestampLogger) Log(message string) error {
timestampedMessage := fmt.Sprintf("%s: %s", time.Now().Format(time.RFC3339), message)
return l.Logger.Log(timestampedMessage)
}
func main() {
var logger Logger
// 使用带时间戳的JSONLogger
logger = &TimestampLogger{Logger: &JSONLogger{}}
logger.Log("Decorated JSON")
}