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…