模板模式是一种行为设计模式,它定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板模式使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
在 Go 中,模板模式通常通过定义一个抽象基类来实现,该类定义了算法的骨架,并将一些可变的方法留给子类来实现。
以下是一个使用模板模式的示例,假设我们有一个简单的日志系统,需要在日志信息中添加时间戳。我们可以使用模板模式来定义一个抽象日志记录器,它定义了一个记录日志的算法骨架,而将时间戳的生成留给具体的子类实现。
首先,我们定义一个抽象日志记录器 LogRecorder,它有一个记录日志的方法 RecordLog,该方法定义了一个日志记录的算法骨架,它包括生成时间戳、记录日志、以及输出日志等步骤:
type LogRecorder interface {
RecordLog(msg string)
}
type BaseLogRecorder struct{}
func (r *BaseLogRecorder) RecordLog(msg string) {
timestamp := r.GenerateTimestamp()
logMsg := fmt.Sprintf("[%s] %s", timestamp, msg)
r.Log(logMsg)
r.Output(logMsg)
}
func (r *BaseLogRecorder) GenerateTimestamp() string {
return time.Now().Format("2006-01-02 15:04:05")
}
func (r *BaseLogRecorder) Log(msg string) {
// 留给子类实现
}
func (r *BaseLogRecorder) Output(msg string) {
// 留给子类实现
}
在上述代码中,我们定义了一个抽象基类 BaseLogRecorder,它实现了一个 RecordLog 方法,该方法定义了日志记录的算法骨架,包括生成时间戳、记录日志和输出日志等步骤。GenerateTimestamp 方法用于生成时间戳,Log 方法和 Output 方法留给子类实现。
接下来,我们可以定义一个具体的日志记录器 FileLogRecorder,它继承自 BaseLogRecorder 并实现 Log 和 Output 方法:
type FileLogRecorder struct {
filename string
}
func NewFileLogRecorder(filename string) *FileLogRecorder {
return &FileLogRecorder{filename}
}
func (r *FileLogRecorder) Log(msg string) {
f, err := os.OpenFile(r.filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
defer f.Close()
if _, err := f.WriteString(msg + "\n"); err != nil {
panic(err)
}
}
func (r *FileLogRecorder) Output(msg string) {
fmt.Println(msg)
}
在上述代码中,我们定义了一个具体的日志记录器 FileLogRecorder,它继承自 BaseLogRecorder 并实现 Log 和 Output 方法。Log 方法将日志记录到文件中,Output 方法将日志输出到控制台中。我们也可以定义其他类型的日志记录器,只需继承 BaseLogRecorder 并实现相应的方法即可。
接下来,我们定义一个 LogRecorderFactory 工厂类,用于根据不同的日志类型创建相应的日志记录器:
type LogRecorderFactory struct{}
func (factory *LogRecorderFactory) CreateLogRecorder(logType string) LogRecorder {
switch logType {
case "file":
return &FileLogRecorder{}
case "console":
return &ConsoleLogRecorder{}
default: return nil
}
}
在上述代码中,我们定义了一个 CreateLogRecorder 方法,它接收一个字符串类型的参数 logType,根据不同的 logType 返回相应的日志记录器。如果 logType 无效,则返回 nil。
最后,我们可以使用 LogRecorderFactory 创建不同类型的日志记录器并使用它们:
factory := &LogRecorderFactory{}
fileLogRecorder := factory.CreateLogRecorder("file")
fileLogRecorder.Log("This is a file log")
fileLogRecorder.Output("This is a file log output")
consoleLogRecorder := factory.CreateLogRecorder("console")
consoleLogRecorder.Log("This is a console log")
consoleLogRecorder.Output("This is a console log output")
在上述代码中,我们使用 LogRecorderFactory 创建了两个不同类型的日志记录器:FileLogRecorder 和 ConsoleLogRecorder,并分别记录和输出日志信息。由于使用了模板模式,我们可以在不修改代码结构的情况下,轻松添加新的日志记录器类型。