DesignPattenTemplate模板模式
DesignPattenTemplate模板模式
通过把不变行为搬移到超类,去除子类中的重复代码,提供了一个很好的代码复用平台
实际案例1
下载场景
UML图
实现代码
package templatemethod
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() {
fmt.Print("default save\n")
}
type HTTPDownloader struct {
*template
}
func NewHTTPDownloader() Downloader {
downloader := &HTTPDownloader{}
template := newTemplate(downloader)
downloader.template = template
return downloader
}
func (d *HTTPDownloader) download() {
fmt.Printf("download %s via http\n", d.uri)
}
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)
}
# 测试代码以及输出
package templatemethod
func ExampleHTTPDownloader() {
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 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
}
核心
代码核心
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")
}
遗漏知识核心
结构体嵌套一个实现接口的弄一个结构体,这个结构体就是实现了那个接口
package my
import "fmt"
type Iface interface {
MethodFace()
}
type StcA struct {}
func (sa *StcA) MethodFace() {
fmt.Println("接口方法")
}
type StcB struct {
*StcA
}
func Verify() Iface {
sb := &StcB{}
return sb
}
func TTmain() {
verify := Verify()
verify.MethodFace()
}
# 测试ttmain()输出
接口方法
PASS
ok g-a/14_template_method/my 0.264s
实际案例2
场景模拟
实现那还女孩出门差别
UML
代码实现
package my
import "fmt"
type IPerson interface {
SetName(name string)
BeforeOut()
Out()
}
type Person struct {
Specific IPerson
name string
}
func (p *Person) SetName(name string) {
p.name = name
}
func (p *Person) BeforeOut() {
if p.Specific == nil {
return
}
p.Specific.BeforeOut()
}
func (p *Person) Out() {
p.BeforeOut()
fmt.Println(p.name + " go out...")
}
// 实现子类Boy以及Girl
type Boy struct {
Person
}
func (b *Boy) BeforeOut() {
fmt.Println("get up...")
}
type Girl struct {
Person
}
func (g *Girl) BeforeOut() {
fmt.Println("get up and 化妆一万个小时的装束...")
}
// 客户端调用
func TTmain() {
person := &Person{}
person.Specific = &Boy{}
person.SetName("zhangshan")
person.Out()
fmt.Println("----------------------")
person.Specific = &Girl{}
person.SetName("lisi")
person.Out()
}
# 测试输出
get up...
zhangshan go out...
----------------------
get up and 化妆一万个小时的装束...
lisi go out...
总结
特征提取父类的方法重写