23

Golang设计模式之建造者模式

 3 years ago
source link: https://studygolang.com/articles/30883
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

建造者模式

GitHub代码链接

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。

什么是建造者模式

一个Builder类会一步一步构造最终的对象,该Builder类是独立于其他对象的。

解决的问题

主要解决在软件系统中,有时候面临一个复杂对象的创建工作,通常这个复杂对象由各个部分的子对象用一定的算法构建成。由于需求的变化,这个复杂对象的各个部分通常会出现巨大的变化,所以,将各个子对象独立出来,容易修改。

例如肯德基的点餐系统,汉堡,薯条,可乐,炸鸡是不变的,变化的是他们组合出的套餐,所以点餐系统使用建造者模式,非常容易拓展出不同的套餐,而且既定的套餐,修改薯条为大份的时候,也非常方便。

优点

  • 将一个系统中的变与不变分离,容易拓展
  • 便于控制细节风险

缺点

  • 产品必须有共同特点,范围有限
  • 如果子类变化复杂,会有很多建造类

代码实现

我们以肯德基的点餐系统为例,实现建造者模式。

1.1 创建所有商品的接口

//Item 所有商品的接口
type Item interface {
    Name() string
    Price() float32
}

1.2 实现食物的接口和类

//Food 食物的接口
type Food interface {
    Kind() string
}

//Staple 主食,食物接口的实例
type Staple struct{}

//Drink 饮料,食物接口的实例
type Drink struct{}

//Snack 小吃,食物接口的实例
type Snack struct{}

//Kind 获取主食类型名称
func (staple Staple) Kind() string {
    return "staple"
}

//Kind 获取饮料类型名称
func (drink Drink) Kind() string {
    return "drink"
}

//Kind 获取小吃类型名称
func (snack Snack) Kind() string {
    return "snack"
}

1.3 实现可口可乐商品

这里我们的饮料继承自1.2中的Drink类,但是Golang没有继承这个概念,我们使用组合来实现继承的效果。

//CocaCola 可口可乐商品类,实现Item接口,并且组合了Drink基类
type CocaCola struct {
    Drink
}

//NewCocaCola 实例化可口可乐
func NewCocaCola() *CocaCola {
    return &CocaCola{}
}

//Name 获取可口可乐商品名
func (co *CocaCola) Name() string {
    return "coca-cola"
}

//Price 获取可口可乐价格
func (co *CocaCola) Price() float32 {
    return 2.5
}

1.4 实现薯条商品类

同样的,薯条类组合了1.2中的Snack类

//Chips 薯条商品类,实现Item接口,组合Snack基类
type Chips struct {
    Snack
}

//NewChips 实例化薯条类
func NewChips() *Chips {
    return &Chips{}
}

//Name 获取薯条的名称
func (ch *Chips) Name() string {
    return "chips"
}

//Price 获取薯条价格
func (ch *Chips) Price() float32 {
    return 9.9
}

1.5 实现汉堡商品类

牛肉汉堡组合了1.2中的Staple类

//BeefBurger 牛肉汉堡,实现Item接口,组合Staple基类
type BeefBurger struct {
    Staple
}

//NewBeefBurger 实例化牛肉汉堡
func NewBeefBurger() *BeefBurger {
    return &BeefBurger{}
}

//Name 获取牛肉汉堡名称
func (bf *BeefBurger) Name() string {
    return "beefBurger"
}

//Price 获取牛肉汉堡价格
func (bf *BeefBurger) Price() float32 {
    return 19.8
}

1.6 实现点单机器

//Meal 点单类
type Meal struct {
    Items *list.List
}

//NewMeal 实例化点单类
func NewMeal() *Meal {
    l := list.New()
    return &Meal{l}
}

//AddItem 添加新的商品
func (m *Meal) AddItem(item Item) {
    m.Items.PushBack(item)
}

//GetCost 获取当前订单总额
func (m *Meal) GetCost() float32 {
    var cost float32 = 0
    for i := m.Items.Front(); i != nil; i = i.Next() {
        item, ok := (i.Value).(Item)
        if ok {
            cost += item.Price()
        }
    }
    return cost
}

//ShowItems 显示当前所有餐品
func (m *Meal) ShowItems() {
    for i := m.Items.Front(); i != nil; i = i.Next() {
        item, ok := (i.Value).(Item)
        if ok {
            fmt.Println(item.Name(), ": ", item.Price(), "元")
        }
    }
}

有疑问加站长微信联系

iiUfA3j.png!mobile

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK