模板方法用于保证同一接口/抽象类的多个实现的某个行为步骤不变,但是每个步骤的具体行为可子类自己确定。比如对于角色抽象类都有着装的过程,且着装过程均是穿上装、穿下装、穿鞋,但是具体的着装不同角色不一样。这个例子不太好,不过已经表达意思了。
php实现
abstract class Role {
abstract public function dress_tops();
abstract public function dress_bottoms();
abstract public function dress_shoes();
final public function dress() {
$this->dress_tops();
$this->dress_bottoms();
$this->dress_shoes();
}
}
class Man extends Role {
public function dress_tops() {
echo "shirts";
}
public function dress_bottoms() {
echo "pants";
}
public function dress_shoes() {
echo "leather shoes";
}
}
class Woman extends Role {
public function dress_tops() {
echo "skirts";
}
public function dress_bottoms() {
echo "skirts";
}
public function dress_shoes() {
echo "heels";
}
}
$man = new Man;
$man->dress();
下面是go语言实现(并不优雅,关于这块的讨论参考我的一篇文章)
package main
import (
"fmt"
)
type Base struct {
this I
}
type ChildA struct {
*Base
}
type ChildB struct {
*Base
}
type I interface {
Init(I) // final
FinalTemplate() // final
test()
}
func (t *Base) Init(i I) {
t.this = i
}
func (t *Base) FinalTemplate() {
fmt.Println("Base-Before")
t.this.test()
fmt.Println("Base-After")
}
func (t *Base) test() {
fmt.Println("Base")
}
func (t *ChildA) test() {
fmt.Println("ChildA")
}
func (t *ChildB) test() {
fmt.Println("ChildB")
}
func FactoryChild(name string) (child I) {
switch name {
case "A":
child = &ChildA{&Base{}}
case "B":
child = &ChildB{&Base{}}
}
child.Init(child)
return
}
func main() {
child := FactoryChild("A")
child.FinalTemplate()
}