模板模式
1.介绍
概念
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
主要作用
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
解决的问题
一些方法通用,却在每一个子类都重新写了这一方法。
使用场景
1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。
(引用自菜鸟教程)
2.实现
背景
创建一个汽车的抽象类,定义启动,行驶和熄火三个方法,再定义一个final类型的work方法,里面执行了上述三个方法,即把work作为模板方法。
java实现
1.创建Car抽象类
public abstract class Car {
abstract void start();
abstract void run();
abstract void shut();
public final void work() {
//启动汽车
start();
//汽车在行驶
run();
//汽车熄火
shut();
}
}
2.创建BenzCar类
public class BenzCar extends Car{
@Override
void start() {
System.out.println("BenzCar is starting...");
}
@Override
void run() {
System.out.println("BenzCar is runnning...");
}
@Override
void shut() {
System.out.println("BenzCar is shutting...");
}
}
3.创建GmCar类
public class GmCar extends Car{
@Override
void start() {
System.out.println("GmCar is starting...");
}
@Override
void run() {
System.out.println("GmCar is runnning...");
}
@Override
void shut() {
System.out.println("GmCar is shutting...");
}
}
- 创建测试类
public class TemplatePatternDemo {
public static void main(String[] args) {
Car gmCar = new GmCar();
Car benzCar = new BenzCar();
benzCar.work();
System.out.println(".........");
gmCar.work();
}
}
6.运行结果
BenzCar is starting…
BenzCar is runnning…
BenzCar is shutting…
…
GmCar is starting…
GmCar is runnning…
GmCar is shutting…
golang实现
package TemplatePattern
import "fmt"
// Template 创建一个模板接口
type Template interface {
start()
run()
shut()
}
// Car 创建一个汽车类,里面有一个模板接口的字段
type Car struct {
Template
}
//汽车类中有一个work方法,调用了模板类中的三个方法
func (c *Car) work() {
//启动汽车
c.Template.start()
//汽车在行驶
c.Template.run()
//汽车熄火
c.Template.shut()
}
// BenCar BenCar类继承了Car类,且实现了Template接口
type BenCar struct {
Car
}
func (b *BenCar) start() {
fmt.Println("BenzCar is starting...")
}
func (b *BenCar) run() {
fmt.Println("BenzCar is runnning...")
}
func (b *BenCar) shut() {
fmt.Println("BenzCar is shuting...")
}
func NewBenCar() *BenCar {
return &BenCar{
//BenCar的构造函数,新建了一个BenCar作为Car中的Template实例(不然调用work会出现panic,因为Car中的template将没有实例)
Car{new(BenCar)},
}
}
type GmCar struct {
Car
}
func (g *GmCar) start() {
fmt.Println("GmCar is starting...")
}
func (g *GmCar) run() {
fmt.Println("GmCar is runnning...")
}
func (g *GmCar) shut() {
fmt.Println("GmCar is shutting...")
}
func NewGmCar() *GmCar {
return &GmCar{
Car{new(GmCar)},
}
}
package TemplatePattern
import (
"fmt"
"testing"
)
func TestTemplateDemo(t *testing.T) {
benCar := NewBenCar()
benCar.work()
fmt.Println("......")
gmCar := NewGmCar()
gmCar.work()
}
=== RUN TestTemplateDemo
BenzCar is starting...
BenzCar is runnning...
BenzCar is shuting...
......
GmCar is starting...
GmCar is runnning...
GmCar is shutting...
--- PASS: TestTemplateDemo (0.00s)
PASS