GOLANG实现模板模式

模板模式可以把一个流程抽象起来,一个流程中首先调用哪一个函数,后面再调用哪一个函数,基本的流程基本是固定的。只是每一步要怎么做跟具体类型有关系,这时候就很适合用模板模式了。

定义:一个抽象类公开定义了执行它的方法的方式/模板。 它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。 这种类型的设计模式属于行为型模式

但是在GOLANG的实现中,需要用到这些知识:当一个子类通过直接在子类中添加父类类型名的方法组合,如果子类没有覆盖父类的方法,那么可以直接通过子类调用父类;如果子类覆盖了父类的方法,那么就会使用子类新定义的方法。

模板实现代码:

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")
}

/*
这里 HTTPDownloader struct包含(封装)了*template, 因为*template实现了Download(uri string)方法,
在我们HTTPDownloader.Download(sting)的时候,其实调用的是*template实现的那一个,这里也是允许认为HTTPDownloader实现了
Download(uri string)方法的,所以可以将HTTPDownloader实例赋值给Downloader实例。就像下面的NewHTTPDownloader()函数直接
将HTTPDownloader实例赋值给Downloader实例那样子。如果我们在HTTPDownloader结构体中添加其他的东西导致HTTPDownloader.Download(sting)
这个调用失败,NewHTTPDownloader()这个函数就编译不通过了。
*/
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)
}
/*
这里如果我把下面的save函数注释掉,*HTTPDownloader.save()则会调用 *template 实现的save()方法。
上层的把底层的覆盖了,这个有点用处。
*/
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

import "testing"

func TestHTTPDownloader(t *testing.T)  {
	var downloader Downloader = NewHTTPDownloader()

	downloader.Download("http://example.com/abc.zip")

}

func TestFTPDownloader(t *testing.T) {
	var downloader Downloader = NewFTPDownloader()

	downloader.Download("ftp://example.com/abc.zip")
}

 结果:
=== RUN   TestHTTPDownloader
prepare downloading
download http://example.com/abc.zip via http
http save //这里使用了http类型实现的save方法。
finish downloading
--- PASS: TestHTTPDownloader (0.00s)
=== RUN   TestFTPDownloader
prepare downloading
download ftp://example.com/abc.zip via ftp
default save  //ftp类没有save方法,直接调用默认的*template.save方法
finish downloading
--- PASS: TestFTPDownloader (0.00s)
PASS

Process finished with exit code 0
 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值