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...

总结

特征提取父类的方法重写

posted @ 2020-12-12 20:06  maob  阅读(92)  评论(0编辑  收藏  举报