设计模式 - 建造者模式
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。
如何解决:将变与不变分离开。
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
应用实例: 1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。 2、JAVA 中的 StringBuilder。
优点: 1、建造者独立,易扩展。 2、便于控制细节风险。
缺点: 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。
使用场景: 1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。
注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
package main import "fmt" type Item interface { GetName() string Packing() string GetPrice() int } type Packing interface { Pack() string } type Wrapper struct{} type Bottle struct{} func (w *Wrapper) Pack() string { return "Wrapper" } func (b *Bottle) Pack() string { return "Bottle" } type Burger struct { packing Packing } func NewBurger() *Burger { return &Burger{&Wrapper{}} } func (b *Burger) Packing() string { return b.packing.Pack() } func (b *Burger) GetName() string { return "burger" } func (b *Burger) GetPrice() int { return 1 } type ColdDrink struct { packing Packing } func NewColdDrink() *ColdDrink { return &ColdDrink{&Bottle{}} } func (c *ColdDrink) Packing() string { return c.packing.Pack() } func (c *ColdDrink) GetName() string { return "cold drink" } func (c *ColdDrink) GetPrice() int { return 2 } type VegBurger struct { Burger *Burger } func (v *VegBurger) GetName() string { return "veg burger" } func (v *VegBurger) GetPrice() int { return v.Burger.GetPrice() } func (v *VegBurger) Packing() string { return v.Burger.Packing() } type ChickenBurger struct { Burger *Burger } func (c *ChickenBurger) GetName() string { return "chicken burger" } func (c *ChickenBurger) GetPrice() int { return c.Burger.GetPrice() } func (c *ChickenBurger) Packing() string { return c.Burger.Packing() } type Coke struct { ColdDrink *ColdDrink } func (c *Coke) GetName() string { return "coke" } func (c *Coke) GetPrice() int { return 2 } func (c *Coke) Packing() string { return c.ColdDrink.Packing() } type Pepsi struct { ColdDrink *ColdDrink } func (p *Pepsi) GetName() string { return "pepsi" } func (p *Pepsi) GetPrice() int { return 3 } func (p *Pepsi) Packing() string { return p.ColdDrink.Packing() } type Meal struct { Items []Item } func (m *Meal) AddItem(item Item) { m.Items = append(m.Items, item) } func (m *Meal) GetCost() int { sum := 0 for _, i := range m.Items { sum += i.GetPrice() } return sum } func (m *Meal) ShowItems() { for _, i := range m.Items { fmt.Println("item: ", i.GetName()) fmt.Println("packing with: ", i.Packing()) fmt.Println("price: ", i.GetPrice()) } } func main() { meal := &Meal{Items: []Item{}} meal.AddItem(&VegBurger{Burger: NewBurger()}) meal.AddItem(&ChickenBurger{Burger: NewBurger()}) meal.AddItem(&ChickenBurger{Burger: NewBurger()}) meal.AddItem(&Coke{ColdDrink: NewColdDrink()}) meal.AddItem(&Pepsi{ColdDrink: NewColdDrink()}) fmt.Println("total cost: ", meal.GetCost()) meal.ShowItems() }