在上一篇博客设计模式-装饰者模式中我们介绍了如何在golang中实现装饰者模式,今天我们接着上篇博客继续设计模式系列文章,今天还是来看一个简单的设计模式-建造者模式。
介绍
相信做过android的同学对建造者模式还是比较熟悉的, 一定用过开源的图片加载框架ImageLoader吧, 在ImageLoader的配置中我们就使用了建造者模式, 那什么是建造者模式呢?来看一下定义:
将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。
建造者模式中有一下几个角色需要我们熟悉:
- Product 这是我们要创建的复杂对象(一般都是很复杂的对象才需要使用建造者模式)。
- Builder 抽象的一个东西, 主要是用来规范我们的建造者的。
- ConcreteBuilder 具体的Builder实现, 这是今天的重点,主要用来根据不用的业务来完成要创建对象的组建的创建。
- Director 这个的作用是规范复杂对象的创建流程。
在来看看创建模式的结构图:
好了,了解了什么是建造者以及建造者中涉及的几个角色,下面我们就来用代码实现一下建造者模式,根据上面提到的几个角色,我们依依用代码来实现它。 今天我们用一个游戏中的角色创建的事例来展示代码,我们这个游戏角色很简单,仅仅包含名称和使用的武器两个字段。
创建复杂对象
首先我们来创建具体的游戏人物类
type Character struct {
Name string
Arms string
}
func (p *Character) SetName(name string) {
p.Name = name
}
func (p *Character) SetArms(arms string) {
p.Arms = arms
}
func (p Character) GetName() string {
return p.Name
}
func (p Character) GetArms() string {
return p.Arms
}
这个类很简单,除了包含我们上面提到了名称和使用的武器两个字段外,剩下的代码仅仅是为这两个字段提供getter和setter方法了,这里不多说了,下面我们就根据这个类来创建一个建造者接口。
实现抽象建造者接口
type Builder interface {
SetName(name string) Builder
SetArms(arms string) Builder
Build() *Character
}
前两个方法是我们根据游戏人物类设计出来的,最后一个Build
方法用来返回我们创建的游戏人物对象。
创建具体的创建者类
下面我们就来根据上面定义的接口来实现一个具体的创建者类,
type CharacterBuilder struct {
character *Character
}
func (p *CharacterBuilder) SetName(name string) Builder {
if p.character == nil {
p.character = &Character{}
}
p.character.SetName(name)
return p
}
func (p *CharacterBuilder) SetArms(arms string) Builder {
if p.character == nil {
p.character = &Character{}
}
p.character.SetArms(arms)
return p
}
func (p *CharacterBuilder) Build() *Character {
return p.character
}
这个结构体实现了上面定义的接口Builder
的所有方法,所以它实现了Builder
接口,并且它还拥有一个Character
的变量,我们就是用来创建这个类型的实例。Build
方法最后返回我们创建的游戏角色对象。
Director的实现
上面说过,Director
的作用主要是规范对象的组件的创建流程,来看看它的实现吧:
type Director struct {
builder Builder
}
func (p Director) Create(name string,arms string) *Character {
return p.builder.SetName(name).SetArms(arms).Build()
}
他需要一个Builder
的实例,所以我们在创建Director
的时候需要定义一个Builder
的具体实现,Director
只有一个方法-Create
方法,我们通过调用Create
方法来根据参数创建具体的游戏角色。
最后我们再来看看如何使用:
func main() {
var builder Builder = &CharacterBuilder {}
var director *Director = &Director {builder: builder}
var character *Character = director.Create("loader","AK47")
fmt.Println(character.GetName() + "," + character.GetArms())
}
首先我们创建了一个Builder
具体实现的实例,接着将他给Director
的实例,最后我们通过调用Director
的Create
方法来完成具体游戏角色的创建。最后我们再强调一点,什么时候使用创建者模式? 当一个对象并不是很复杂的时候不太适用创建者模式,当我们需要创建的对象特别复杂的时候才考虑使用创建者模式实现。
代码放github上了,欢迎star: https://github.com/qibin0506/go-designpattern