define

The template approach is to define an algorithm skeleton in a method and postpone the implementation of these steps to subclasses. The template approach allows subclasses to redefine certain steps without changing the overall structure of the algorithm.

The algorithm here can be thought of as business logic.

Application scenarios

Extensions: Frameworks provide functional extension points through templates that allow framework users to customize the functionality of the framework based on the extension points without modifying the source code. Reuse: Reuse means that subclasses can take the code of the parent class’s diurnal template method.

And callbacks

Synchronous callback

  • Callbacks are implemented based on a composition relationship, which is a relationship between objects passing one object to another
  • The template pattern is implemented based on inheritance relationships, and subclasses override freys abstract methods, which are relationships between classes.

An asynchronous callback

  • It’s more of an observer mode

code

package template
import "fmt"

type Downloader interface {
	Download(uri string)}type template struct {
	implement
	uri string
}

type implement interface {
	download()
	save()
}

func newTemplate(impl implement) *template {
	return &template{
		implement: impl,
	}
}

func (t *template) Download(uri string) {
	t.uri = uri
	fmt.Print("prepare downloading\n")
	t.implement.download()
	t.implement.save()
	fmt.Print("finish downloading\n")}func (t *template) save(a) {
	fmt.Print("default save\n")}type HTTPDownloader struct {
	*template
}

func NewHTTPDownloader(a) Downloader {
	downloader := &HTTPDownloader{}
	template := newTemplate(downloader)
	downloader.template = template
	return downloader
}

func (d *HTTPDownloader) download(a) {
	fmt.Printf("download %s via http\n", d.uri)
}

func (*HTTPDownloader) save(a) {
	fmt.Printf("http save\n")}type FTPDownloader struct {
	*template
}

func NewFTPDownloader(a) Downloader {
	downloader := &FTPDownloader{}
	template := newTemplate(downloader)
	downloader.template = template
	return downloader
}

func (d *FTPDownloader) download(a) {
	fmt.Printf("download %s via ftp\n", d.uri)
}

Copy the code

The test code

package template

import "testing"

func TestExampleHTTPDownloader(t *testing.T) {
	var downloader Downloader = NewHTTPDownloader()

	downloader.Download("http://example.com/abc.zip")
	// Output:
	// prepare downloading
	// download http://example.com/abc.zip via http
	// http save
	// finish downloading
}

func TestExampleFTPDownloader(t *testing.T) {
	var downloader Downloader = NewFTPDownloader()

	downloader.Download("ftp://example.com/abc.zip")
	// Output:
	// prepare downloading
	// download ftp://example.com/abc.zip via ftp
	// default save
	// finish downloading
}

Copy the code

The results

=== RUN TestExampleHTTPDownloader prepare downloading download http://example.com/abc.zip via http http save finish downloading --- PASS: TestExampleHTTPDownloader (0.00 s) = = = RUN TestExampleFTPDownloader prepare downloading the download ftp://example.com/abc.zip via FTP the default save finish downloading - PASS: TestExampleFTPDownloader PASS (0.00 s)Copy the code

The resources

  • Refactoringguru. Cn/design – patt…
  • ​Github.com/senghoo/gol…