mirror of
https://github.com/crazybber/go-pattern-examples.git
synced 2024-11-22 03:46:03 +03:00
finish template_method pattern
This commit is contained in:
parent
87d44adc6d
commit
0932602a56
@ -1,9 +1,17 @@
|
||||
# 模版方法模式
|
||||
|
||||
模板方法就是为了将方法和结构各自实现分开到不同的地方,并且可以单独实现,往往是将将方法/处理器的实现延迟到子类或者其他可注入的类型中。
|
||||
模板方法主要是为了解决一些方法通用性问题,将通用方法放在父类,需要单独实现的方法放在其他类中,将通用方法和变化的方法分开,各自实现分开到不同的地方,并且可以单独实现,往往是将将变化部分方法/处理器的实现延迟到子类或者其他可注入的类型中。
|
||||
|
||||
模板方法就是设计的核心思想体现,如果把其他的模式都忘了,只要还记得一个模式,就能变化其他的任意模块,设计模式的作用要点就是要封装变化点,尽量降低耦合,方法,结构分离,接口继承,结构继承,都是为了将不同的变化点封装到不同的模块,以使其能够单独演化,尽量做到通用。
|
||||
|
||||
go 的结构对象和接口的分离做的更彻底,不需要像其他语言一样显式声明继承或者实现关系,所以在实现模板方法时候更灵活。
|
||||
|
||||
此处需要注意:因为父类需要调用子类方法,所以子类需要匿名组合父类的同时,父类需要持有子类的引用。
|
||||
模板方法的特点在于,定义一好一套接口,定义基本类型结构作为父类,同时在父类中组合好调用方式,并实现好通用的方法,变化部分的接口的具体实现可以在子类或者其他地方实现。
|
||||
|
||||
现实生活中工作中,文件打印就是一个很好的模板方法的例子,我们打印操作一般式:
|
||||
|
||||
文件--->设置--->打印.
|
||||
|
||||
但是对于不同的打印方式对于同一个文件的打印实现可能略有不同。
|
||||
|
||||
比如虚拟打印到 pdf或者xps与打印打纸质文件需要的设置和打印肯定式不同的,虚拟打印你肯定需要指明输出路径,纸质打印需要可能需要设置打印质量,质量越高,越费墨。
|
||||
|
||||
|
@ -2,68 +2,78 @@ package templatemethod
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Downloader interface {
|
||||
Download(uri string)
|
||||
////////////////////////////////
|
||||
//使用打印的例子
|
||||
|
||||
//IPrinter 定义打印的流程
|
||||
type IPrinter interface {
|
||||
Set(mark string)
|
||||
Print()
|
||||
}
|
||||
|
||||
type template struct {
|
||||
implement
|
||||
uri string
|
||||
//Printer 定义基本结构类型
|
||||
type Printer struct {
|
||||
workerMark string
|
||||
printer IPrinter //指项实际工作的类型
|
||||
}
|
||||
|
||||
type implement interface {
|
||||
download()
|
||||
save()
|
||||
//LoadDrive 载入驱动
|
||||
func (p *Printer) LoadDrive() {
|
||||
fmt.Print("init print drive\n")
|
||||
}
|
||||
|
||||
func newTemplate(impl implement) *template {
|
||||
return &template{
|
||||
implement: impl,
|
||||
//UnLoadDrive 卸载驱动
|
||||
func (p *Printer) UnLoadDrive() {
|
||||
fmt.Print("unload drive\n")
|
||||
}
|
||||
|
||||
//Set 设置参数,这是变化的部分
|
||||
func (p *Printer) Set(mark string) {
|
||||
p.workerMark = mark
|
||||
//调用实现
|
||||
if p.printer != nil {
|
||||
p.printer.Set(mark)
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
//Print 执行打印,这是变化的部分
|
||||
func (p *Printer) Print() {
|
||||
//调用实现
|
||||
fmt.Print("print with task mark: ", p.workerMark, "\n")
|
||||
if p.printer != nil {
|
||||
p.printer.Print()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (t *template) save() {
|
||||
fmt.Print("default save\n")
|
||||
//DoPrintWork 打印
|
||||
//DoPrintWork 定义了打印的流程
|
||||
func (p *Printer) DoPrintWork() {
|
||||
p.LoadDrive()
|
||||
p.Set(p.workerMark)
|
||||
p.Print()
|
||||
p.UnLoadDrive()
|
||||
}
|
||||
|
||||
type HTTPDownloader struct {
|
||||
*template
|
||||
//PDF 虚拟打印
|
||||
type PDF struct {
|
||||
Printer
|
||||
output string
|
||||
}
|
||||
|
||||
func NewHTTPDownloader() Downloader {
|
||||
downloader := &HTTPDownloader{}
|
||||
template := newTemplate(downloader)
|
||||
downloader.template = template
|
||||
return downloader
|
||||
//Print to a PDF
|
||||
func (p *PDF) Print() {
|
||||
fmt.Print("print to PDF ,save to ", p.output, "\n")
|
||||
|
||||
}
|
||||
|
||||
func (d *HTTPDownloader) download() {
|
||||
fmt.Printf("download %s via http\n", d.uri)
|
||||
//DevicePrinter 设备打印机
|
||||
type DevicePrinter struct {
|
||||
Printer
|
||||
quality int //1,2,3表示打印高中低
|
||||
}
|
||||
|
||||
func (*HTTPDownloader) save() {
|
||||
fmt.Printf("http save\n")
|
||||
}
|
||||
|
||||
type FTPDownloader struct {
|
||||
*template
|
||||
}
|
||||
|
||||
func NewFTPDownloader() Downloader {
|
||||
downloader := &FTPDownloader{}
|
||||
template := newTemplate(downloader)
|
||||
downloader.template = template
|
||||
return downloader
|
||||
}
|
||||
|
||||
func (d *FTPDownloader) download() {
|
||||
fmt.Printf("download %s via ftp\n", d.uri)
|
||||
//Print to a Paper
|
||||
func (d *DevicePrinter) Print() {
|
||||
fmt.Print("print to Paper ,with quality: ", d.quality, "\n")
|
||||
}
|
||||
|
@ -1,23 +1,27 @@
|
||||
package templatemethod
|
||||
|
||||
func ExampleHTTPDownloader() {
|
||||
var downloader Downloader = NewHTTPDownloader()
|
||||
import "testing"
|
||||
|
||||
func TestTemplateMethod(t *testing.T) {
|
||||
|
||||
//打印机
|
||||
aprinter := Printer{}
|
||||
|
||||
//这个是被复合的work流程
|
||||
aprinter.DoPrintWork()
|
||||
|
||||
//连接PDF打印机
|
||||
aprinter.printer = &PDF{output: "./home"}
|
||||
|
||||
aprinter.Set("---PDF--")
|
||||
//打印
|
||||
aprinter.DoPrintWork()
|
||||
|
||||
//连接纸质打印机
|
||||
aprinter.printer = &DevicePrinter{quality: 5}
|
||||
|
||||
aprinter.Set("---Paper--")
|
||||
//打印
|
||||
aprinter.DoPrintWork()
|
||||
|
||||
downloader.Download("http://example.com/abc.zip")
|
||||
// Output:
|
||||
// prepare downloading
|
||||
// download http://example.com/abc.zip via http
|
||||
// http save
|
||||
// finish downloading
|
||||
}
|
||||
|
||||
func ExampleFTPDownloader() {
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user