Escritura de combate de patrón de fábrica de Golang

¡Trabajar juntos para crear y crecer juntos! Este es el día 33 de mi participación en el "Nuggets Daily New Plan·Desafío de actualización de agosto", haga clic para ver los detalles del evento

Hoy les mostrare como usar Go para escribir el codigo del patron de fabrica, aprendamos un caso practico. El autor suele utilizar este método de escritura todos los días, y puede ayudar de manera efectiva a todos a lograr la Separación de preocupaciones.

Retire la placa base

La placa principal es el flujo principal de un programa. Por ejemplo, necesitamos digerir y absorber conocimientos basados ​​en un material de aprendizaje. Podemos tener los siguientes pasos:

  1. preparar un cuaderno;
  2. información abierta;
  3. Lea el contenido del material, piense y registre los puntos clave en el cuaderno;
  4. Haz los ejercicios incluidos en el material;
  5. Resumir y verificar el dominio.

Esta información puede ser un libro en papel, un libro electrónico o una columna en una determinada plataforma. Hay muchas formas, pero no nos importa, porque en el proceso del tema, solo necesita ser un documento y tiene la capacidad. para hacerlo

En otras palabras, convertimos los datos en una interfaz, definida de la siguiente manera:

type KnowledgeMaterial interface{
	GetContent() string
	GetExercises() []string
}
复制代码

Puede darnos el contenido principal y darnos preguntas de práctica, es suficiente para satisfacer estos dos puntos.

Por lo tanto, a la placa base no le importa esencialmente cuál es esta información.

La extensión se basa en la implementación de la interfaz, o de manera análoga al adaptador, es un adaptador. Podemos definir varias extensiones Book, todas las Ebookcuales Columnimplementan esta KnowledgeMaterialinterfaz .

Cuando muchos estudiantes escriben código, no pueden desmontar la placa base y no saben cuál es su proceso central, lo cual es muy importante. Si el [proceso principal] no se puede desarmar, significa que cuando necesita implementar la lógica para una determinada entidad, depende directamente de esta [implementación].

Por ejemplo, en nuestro caso anterior, no hay KnowledgeMaterialinterfaz , su proceso es abrir la primera página del libro en papel, mirar la tabla de contenido, luego pasar al primer capítulo y comenzar a leer el texto del libro. . . .

Esto es algo aterrador, significa que una vez que cambia la estructura, su código es imposible de adaptar. Necesitará varios if else para determinar de qué tipo es. Si hay otro tipo de material de aprendizaje llamado [videocurso], ¿qué debo hacer en este momento?

No hay página que pasar, y la entidad a la que te enfrentas se convierte en contenido de vídeo, no es fácil adaptarse a ella.

所以,大家一定要练习这个能力,遇到问题,思考自己的主流程是什么,拆出主板,然后明确你对业务实体的诉求是什么,能否抽象化。

是一个实现了KnowledgeMaterial 接口的任意实体就 ok?还是必须得是 Book 这个具体的结构体才 ok?

如果你需要的只是个接口,能够抽象简化,就尽量用我们今天要说的工厂模式来做,这样你的主流程心智负担会小很多,此后新增扩展成本也很小。

工厂模式流程

  1. 抽象出对实体的能力要求,变成接口;
  2. 实现工厂,支持适配器注册,支持根据类型获取对应的接口实现;
  3. 主流程只依赖接口完成;
  4. 将你的扩展,变成 adapter 适配器,实现接口所要求的的能力;
  5. 将你的适配器通过第二步里提到的方法,注册到工厂里。

这样的好处就在于,主板和扩展隔离,新增扩展的时候,只需要新增,不需要动主流程,不需要动其他扩展,避免了一大堆 if else 的写法。

代码实战

我们结合一开始提到的 KnowledgeMaterial 接口来简单示例一下。

抽象能力,定义接口

type KnowledgeMaterial interface{
	GetContent() string
	GetExercises() []string
}
复制代码

实现工厂,支持注册和获取实现

新建一个 factory.go 文件,填充如下内容:


type KnowledgeAdapterFactory struct {
	sync.RWMutex
	adapters []KnowledgeAdapter
}

var (
	knowledgeAdapterFactory = KnowledgeAdapterFactory{
		adapters: []KnowledgeAdapter{},
	}
)

// RegisterKnowledgeAdapter 注册新的知识资料适配器
func RegisterKnowledgeAdapter(adapter KnowledgeAdapter) {
	knowledgeAdapterFactory.Lock()
	knowledgeAdapterFactory.adapters = append(knowledgeAdapterFactory.adapters, adapter)
        knowledgeAdapterFactory.Unlock()

}

// GetAllKnowledgeAdapters 获取所有知识资料适配器
func GetAllKnowledgeAdapters() []KnowledgeAdapter {
	return knowledgeAdapterFactory.adapters
}
复制代码

主流程只依赖接口完成

重点关注和 adapter 相关的逻辑,其他部分省略:

func LearnKnowledge() {
	//准备好笔记本
	notes := openNotesForWrite()

	for _, adapter := range GetAllKnowledgeAdapters() {
		content := adapter.GetContent()

		// 阅读资料内容,思考并记录关键点到笔记本上
		writeNotes(content)

		// 做资料里包含的练习题
		for _, ex := range adapter.GetExercises() {
			doExecise(ex)
		}
	}

	// 归纳总结,验证掌握程度
	summary()
}
复制代码

扩展 => 适配器,实现接口

新建一个包:book,用于实现纸质书籍的适配器。在其中新建 adapter.go 文件,填充如下代码

type Adapter struct {}

func (a *Adapter) GetContent() string {
	return "xxx"
}

func (a *Adapter) GetExercises() []string {
	return []string{"xxx"}
}
复制代码

注册适配器到工厂里

这里写法其实相对灵活,很多人会选择直接在工厂定义的 factory.go 写注册逻辑,我个人不太喜欢这样。这就意味着每次新增适配器,都需要动工厂。

比较推荐直接在适配器的 init() 函数中完成注册,然后在 main 函数启动时 import 包进来,就执行了 init 函数。

这样写的好处在于当你新增一个扩展的时候,主流程和工厂都不需要动,只新增文件就好。

我们可以把上面的 adapter.go 新增一个函数即可:

type Adapter struct {}

func init() {
	RegisterKnowledgeAdapter(&Adapter{})
}

func (a *Adapter) GetContent() string {
	return "xxx"
}

func (a *Adapter) GetExercises() []string {
	return []string{"xxx"}
}

复制代码

小结

El modo de fábrica es una forma de escritura muy simple y fácil de usar. El punto clave es que todos deben distinguir la placa base y la expansión, y llenar el adaptador por registro, en lugar de distinguir por si más. Espero que el método de escritura presentado hoy sea útil para usted. Puede haber muchas variantes aquí, y la esencia es similar.

¡Gracias por leer y bienvenido a intercambiar en el área de comentarios!

Supongo que te gusta

Origin juejin.im/post/7136852697872859173
Recomendado
Clasificación