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