模版设计模式

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

介绍

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

主要解决:一些方法通用,却在每一个子类都重新写了这一方法。

何时使用:有一些通用的方法。

如何解决:将这些通用算法抽象出来。

关键代码:在抽象类实现,其他步骤在子类实现。

优点:

  • 封装不变部分,扩展可变部分。
  • 提取公共代码,便于维护。
  • 行为由父类控制,子类实现。

缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使系统更加庞大。

使用场景:

  • 有多个子类共有的方法,且逻辑相同。
  • 重要的、复杂的方法,可以考虑作为模版方法。

注意:为放置恶意操作,一般模版方法都加上final关键字

实现:

代码:

package TemplatePattern

import "fmt"

type Game interface {
	Initialize()
	StartPlay()
	EndPlay()
	Play()
}

type BaseGame struct {
}

func (b *BaseGame) Initialize() {
	fmt.Println("base Initialize")
}
func (b *BaseGame) StartPlay() {
	fmt.Println("base StartPlay")
}
func (b *BaseGame) EndPlay() {
	fmt.Println("base EndPlay")
}
func (b *BaseGame) Play() {
	b.Initialize()
	b.StartPlay()
	b.EndPlay()
}
package TemplatePattern

import "fmt"

type Cricket struct {
	baseGame BaseGame
}

func (c *Cricket) Initialize() {
	fmt.Println("Cricket Game Finished!")
}
func (c *Cricket) StartPlay() {
	fmt.Println("Cricket Game Initialized! Start playing.")
}
func (c *Cricket) EndPlay() {
	c.baseGame.EndPlay()
}
func (c *Cricket) Play() {
	c.Initialize()
	c.StartPlay()
	c.EndPlay()
}
package TemplatePattern

import "fmt"

type Football struct {
	baseGame BaseGame
}

func (f *Football) Initialize() {
	fmt.Println("Football Game Finished!")
}
func (f *Football) StartPlay() {
	f.baseGame.StartPlay()
}
func (f *Football) EndPlay() {
	fmt.Println("Football Game Started. Enjoy the game!")
}
func (f *Football) Play() {
	f.Initialize()
	f.StartPlay()
	f.EndPlay()
}

测试:

func testTemplatePattern() {
	cricket := new(TemplatePattern.Cricket)
	cricket.Play()

	football := new(TemplatePattern.Football)
	football.Play()
}

输出:

Cricket Game Finished!
Cricket Game Initialized! Start playing.
base EndPlay
Football Game Finished!
base StartPlay
Football Game Started. Enjoy the game!