Go设计模式(19)-模板模式

简介: 模板模式定义算法骨架,使用上有两个特征,一是要继承算法骨架,达到复用的目的;二是具体的算法步骤在子类中实现,达到扩展的目的。

模板模式定义算法骨架,使用上有两个特征,一是要继承算法骨架,达到复用的目的;二是具体的算法步骤在子类中实现,达到扩展的目的。

UML类图位置:https://www.processon.com/view/link/60d29bf3e401fd49502afd25

本文代码链接为:https://github.com/shidawuhen/asap/blob/master/controller/design/19template.go

1.定义

1.1模板模式

模板模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

UML:

图片

1.2分析

模板模式的UML图几乎是最简单的了。

**模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。**TemplateMethod是算法骨架,PrimitiveOperation1和PrimitiveOperation2是骨架中的某些步骤。

在模板模式经典的实现中,模板方法定义为 final,可以避免被子类重写。需要子类重写的方法定义为 abstract,可以强迫子类去实现。

以前用这种定义好算法骨架,具体实现在不同子类的方案时,一般使用的是工厂方法加代理模式。工厂方法能够提供更多的灵活性,但如果一个算法骨架中有10个具体算法,总不能让工厂生产10个不同的对象吧。所以如果算法骨架中有多个具体算法,而这些算法又是高内聚的,用模板模式就很合适。

2.使用场景

业务开发场景中,模板模式使用频率并不高,但是在框架方面,还是使用的比较频繁的。

先查看了Gin源码Gin源码剖析,发现用的不是模板模式,其实完全没用啥设计模式,算是用了里氏替换原则。

主框架有Handler接口,用于做路由解析、对应逻辑执行与返回。

type Handler interface {
   ServeHTTP(ResponseWriter, *Request)
}

Gin中的engin实现该接口

// ServeHTTP conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
   c := engine.pool.Get().(*Context)
   c.writermem.reset(w)
   c.Request = req
   c.reset()

   engine.handleHTTPRequest(c)

   engine.pool.Put(c)
}

之所以说没有使用模板模式,主要是因为并没有继承算法框架。

后来想想Go语言没有继承,没法实现经典款模板方法。虽然可以用组合实现模板方法,但无法控制对算法框架的重写、也无法强迫子类重写算法实现,感觉价值不大。有很多更好的方案能够实现目的。

3.代码实现

虽然没什么特别好的case,但是代码还是要写一下的。参考大话设计模式,写一个试卷场景吧。试卷内容确定,但试卷答案不定。

package main

import "fmt"

/**
 * @Author: Jason Pang
 * @Description: 试卷
 */
type Examination struct {
   //函数变量,回答问题1
   Answer1 func()
   //函数变量,回答问题2
   Answer2 func()
}

/**
 * @Author: Jason Pang
 * @Description: 问题列表,也是算法骨架
 * @receiver e
 */
func (e *Examination) Questions() {
   fmt.Println("第一题:谁是最帅的人?")
   e.Answer1()
   fmt.Println("第二题:生活的意义是什么?")
   e.Answer2()
}

/**
 * @Author: Jason Pang
 * @Description: 真正做试卷
 */
type ExamplationDo struct {
   Examination
}

/**
 * @Author: Jason Pang
 * @Description: 写答案1
 * @receiver d
 */
func (d *ExamplationDo) Answer1() {
   fmt.Println("答案:我自己")
}

/**
 * @Author: Jason Pang
 * @Description: 写答案2
 * @receiver d
 */
func (d *ExamplationDo) Answer2() {
   fmt.Println("答案:躺平")
}
func main() {
   e := &ExamplationDo{}
   //需要对父类函数进行赋值
   e.Examination.Answer1 = e.Answer1
   e.Examination.Answer2 = e.Answer2

   e.Questions()
}

输出:

➜ myproject go run main.go

第一题:谁是最帅的人?

答案:我自己

第二题:生活的意义是什么?

答案:躺平

上面的代码使用一些技巧才能实现模板模式。父类Examination实现了算法骨架,同时包含两个函数变量Answer1和Answer2,代表算法实现。子类ExamplationDo实现了Answer1和Answer2,并将这两个函数赋值给父类的函数变量。

总结

模板模式有两大作用:复用和扩展。其中,复用指的是,所有的子类可以复用父类中提供的模板方法的代码。扩展指的是,框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

相关文章
|
15天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
2月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
17天前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###
|
5天前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
10天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
27 1
|
26天前
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
26天前
|
安全 Go 开发者
破译Go语言中的并发模式:从入门到精通
在这篇技术性文章中,我们将跳过常规的摘要模式,直接带你进入Go语言的并发世界。你将不会看到枯燥的介绍,而是一段代码的旅程,从Go的并发基础构建块(goroutine和channel)开始,到高级模式的实践应用,我们共同探索如何高效地使用Go来处理并发任务。准备好,让Go带你飞。
|
1月前
|
设计模式 Java Kotlin
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
本教程详细讲解Kotlin语法,适合希望深入了解Kotlin的开发者。对于快速学习Kotlin语法,推荐查看“简洁”系列教程。本文重点介绍了构建者模式在Kotlin中的应用与改良,包括如何使用具名可选参数简化复杂对象的创建过程,以及如何在初始化代码块中对参数进行约束和校验。
21 3
|
1月前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
34 0
|
2月前
|
设计模式 Java
Java设计模式-工厂方法模式(4)
Java设计模式-工厂方法模式(4)