golang实现设计模式之构建者模式总结-代码、优缺点、适用场景

发布时间 2023-06-01 11:31:35作者: 进击的davis

构建者模式也是一种创建型的设计模式,该模式将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的对象。大白话就是,构建者模式,从输出角度看依然是创建个对象实例,但是构建者模式更关注创建的细节,或者说一个对象的创建可以拆分为多个步骤,所有的步骤完成才创建出这个对象实例,而对于之前分享的工厂模式系列,那些都是偏重于创建简单的实例,侧重点不一样。

下面看看与工厂模式的区别:

  • 1.工厂模式适合创建一样的简单实例,不注重构建细节,构建者模式创建复杂对象。
  • 2.建造者模式更加注重方法的调用顺序,工厂模式注重创建对象。
  • 3.关注重点不一样,工厂模式只需要创建出来即可,构建者模式还需要关注创建过程。
  • 4.工厂模式创建的对象实例都是一样的,构建者如果构建过程不同,创建的对象也不同。

做个简单总结:

  • 创建简单实例,工厂模式。
  • 创建复杂实例,注重创建过程的,请用构建者模式。

老规矩,看看构建者模式的优缺点和适用场景。

优缺点

  • 优点
    1.封装性好,构建和表示分离:对外只需要提供构建的接口即可。
    2.扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
    3.客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险,这相当于对外屏蔽细节,对内自由调整。

  • 缺点
    1.产品的组成部分必须相同,这限制了其使用范围。
    2.如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。

适用场景

当需要创建的产品具备复杂创建过程时,可以抽取出共性创建过程,然后交由具体实现类自定义创建流程,使得同样的创建行为可以生产出不同的产品,分离了创建与表示,使创建产品的灵活性大大增加。

所以构建者模式的适用场景主要是:

  • 1.相同的方法,不同的执行顺序,产生不同的结果。
  • 2.多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同。
  • 3.产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用。
  • 4.初始化一个对象特别复杂,参数多,而且很多参数都具有默认值。

代码实现

package main

import "fmt"

/*
业务场景描述:
   - 代工厂生产iphone,组装iphone的过程简化为组装、出厂测试、打包
这里涉及到的结构主要分为以下四类:
   - 1.产品,iphone手机
   - 2.抽象建造者,即抽象工厂
   - 3.具体建造者,即具体工厂
   - 4.指挥者角色,整合建造者的方法,实现生产产品的流程,最后生产出可直接销售的iphone
 */

// 1.product,为了便于扩展,先写个抽象产品,即接口
type iProduct interface {
   introduction()
}

// concrete product
type iphoneProduct struct {
   name string
}

func (r *iphoneProduct) introduction()  {
   fmt.Println("It's iphone.")
}

// 2.abstract factory, or abstract builder, interface
type IPhoneFactory interface {
   assemble()
   testBeforeSell()
   packaging() *iphoneProduct
}

// 3.concrete builder, or factory
type phoneFactory struct {
}

func (r *phoneFactory) assemble()  {
   fmt.Println("assembling product ...")
}

func (r *phoneFactory) testBeforeSell()  {
   fmt.Println("testing product ...")
}

func (r *phoneFactory) packaging() *iphoneProduct {
   fmt.Println("packaging product ...")
   return &iphoneProduct{"iphone 14 pro max"}
}

// 4.director
type director struct {
   builder phoneFactory
}

func NewDirector() *director {
   return &director{}
}

func (d *director) Set(f phoneFactory)  {
   d.builder = f
}

func (d *director) Gen() *iphoneProduct {
   return d.gen()
}

func (d *director) gen() *iphoneProduct {
   d.builder.assemble()
   d.builder.testBeforeSell()
   return d.builder.packaging()
}

func main()  {
   d := NewDirector()
   d.Set(phoneFactory{})
   phone := d.Gen()
   fmt.Println(phone)
}

参考: