设计模式——模版模式

138 阅读2分钟

模版模式

类型

行为型设计模式

核心思想

模板模式的核心思想是“模板方法模式”,即将算法的核心部分抽象出来,以便子类可以在不改变算法整体结构的情况下重新定义某些步骤。

概述

定义了一个算法的骨架,将一些步骤延迟到子类中实现,从而使得子类可以改变算法的某些特定步骤,但算法的流程不变。模板模式通常由一个抽象基类来实现算法的骨架,其中包含了一些抽象方法,这些方法由子类来实现具体的步骤。同时,抽象基类中也可以包含一些具体的方法,这些方法对于所有子类都是通用的。

也就是将所有重复的都上升到父类,子类进行继承,而不是重复实现

场景

当要完成某一个细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次实现可能不同时,通常考虑模版方法模式处理。

结构图

image.png

主要角色

  1. 抽象类(Abstract Class):定义了一个模板方法,该方法中包含了算法的骨架,同时也可以定义一些具体的方法和抽象方法,抽象方法由子类来实现,(在golang中经常抽象类可以使用接口)。

image.png

  1. 具体类(Concrete Class):继承自抽象类,实现抽象方法,从而完成算法的具体步骤。

image.png

优缺点

优点

让算法的骨架固定下来,从而可以提高代码的可读性。同时,它也可以保证算法的执行顺序,避免了一些潜在的错误。保证逻辑顺序的可靠性。

并且将不变的行为搬运到父类中,有效去除子类中的重复的代码,提高代码的复用性。

缺点

有时会过度使用继承,从而导致代码的可读性和可维护性降低。此外,如果算法的步骤变化太多,那么它可能会成为一个不适合使用模板模式的场景。

demo(golang)

做饮料:

假设有一个制作饮料的流程,包含以下步骤:选材、加工、调味、装杯。其中,选材和加工是必须的步骤,而调味和装杯是可选的步骤,可以在子类中选择实现或者不实现。 整体流程:

type BeverageMaker interface {
    ChooseIngredients()
    Process()
    AddSeasoning()
    PourIntoCup()
}

func makeBeverage(b BeverageMaker) {
    b.ChooseIngredients()
    b.Process()

    if b.hasSeasoning {
       b.AddSeasoning()
    }

    b.PourIntoCup()
}

子类实现:做一杯咖啡

type CoffeeMaker struct {
    hasSeasoning bool
}

func (c *CoffeeMaker) ChooseIngredients() {
    fmt.Println("Choosing coffee beans and water")
}

func (c *CoffeeMaker) Process() {
    fmt.Println("Brewing coffee")
}

func (c *CoffeeMaker) AddSeasoning() {
    c.hasSeasoning = true
    fmt.Println("Adding sugar and milk")
}

func (c *CoffeeMaker) PourIntoCup() {
    fmt.Println("Pouring coffee into cup")
}

实际调用

func main() {
    coffeeMaker := &CoffeeMaker{}
    makeBeverage(coffeeMaker)
}

总结

模版模式可以帮助我们简化复杂的算法,并提高代码的复用性和可维护性