一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
前言
建造者模式介绍
使用多个简单的对象一步一步构建成一个复杂的对象。换句话说,该模式允许使用相同的构造代码生成对象的不同类型和表示。
简介
定义
建造者模式( Builder)隶属于创建型,原理主要是通过组合多个简单的对象来逐步构建一个相对复杂的对象,并且构建这个复杂对象拥有相同的逻辑。
特点
可以逐步创建对象。而这些对象的创建可以推迟到构造对象的所有必要信息可用为止。因为对象的复杂构造与该对象的业务逻辑隔离,所以代码也会清晰干净。
概要
多个简单对象,一个复杂对象。通过组合的形式来表现复杂对象的多元化。
理解实现
现实模型
大家都知道我爱吃果子。经常会买一些不同地域的🍍、🥭、🍇、🥝、🍉,最近老乡推出了一项新业务-果子捞,对于我这种喜欢吃果子的ShuaiGe来说那真是福音啊,以前每天只能吃一种果子,现在每天都有不同的果子吃了,还是下班前买,吃完还是写水文。
分析模型
主线:我买找老乡买丰富的果子捞,吃完写水文。
模型1: 我 -> 消费者
模型2: 老乡新业务 -> 建造工人
模型3: 果子捞 ->复杂产品
我(消费者[shuaige])
一周七天,周一到周五上班摸鱼比较费脑子,又不敢提桶,只能买水果补补,不然怎么卷的过各位大佬。
class Me:ShuaiGe{
fun eatGuoZiLao(){
(1..7).forEach {
when(it){
1-> GuoZiLaoBuilder().choosePineapple().chooseGrape().build()
2->GuoZiLaoBuilder().chooseKiwi().chooseGrape().choosePineapple().build()
3->GuoZiLaoBuilder().choosePineapple().chooseMango().chooseKiwi().chooseWatermelon().build()
4->GuoZiLaoBuilder().chooseWatermelon().chooseKiwi().build()
5->GuoZiLaoBuilder().chooseKiwi().choosePineapple().chooseKiwi().build()
else-> println("周末没赚钱不准吃果子捞")
}
}
}
}
老乡新业务 (建造工人)
class GuoZiLaoBuilder{
var hasPineapple = false
var hasMango= false
var hasGrape= false
var hasKiwi= false
var hasWatermelon= false
fun choosePineapple():GuoZiLaoBuilder{
hasPineapple = true
return this
}
fun chooseMango():GuoZiLaoBuilder{
hasMango = true
return this
}
fun chooseGrape():GuoZiLaoBuilder{
hasGrape = true
return this
}
fun chooseKiwi():GuoZiLaoBuilder{
hasKiwi = true
return this
}
fun chooseWatermelon():GuoZiLaoBuilder{
hasWatermelon = true
return this
}
fun build():GuoZiLao{
var guoZiLao = GuoZiLao(this)
if (hasPineapple) println("加菠萝") else println("不加菠萝")
// ......
return guoZiLao
}
}
果子捞 (复杂产品)
class GuoZiLao{
var pineapple:Pineapple?=null
var mango:Mango?=null
var grape:Grape?=null
var kiwi:Kiwi?=null
var watermelon:Watermelon?=null
constructor(builder: GuoZiLaoBuilder){
if (builder.hasPineapple) pineapple = Pineapple()
if (builder.hasMango) mango = Mango()
// ......
}
}
使用实例
下面以api响应参数处理功能来说,一般情况下我们的响应会带有code、message、data、datalist、extra,这几种参数,但是不是每次API响应都包含所有参数。这种时候就可以使用建造者模式了。
响应对象 -> 复杂对象
class ApiResponse<T>{
var code:Int?=null
var message:String?=null
var data:T?=null
var dataList:List<T>?=null
var extra:Any?=null
constructor(builder: ApiResponseBuilder<T>){
code = builder.code
message = builder.message
data = builder.data as T
dataList = builder.dataList as List<T>
extra = builder.extra
}
}
响应对象builder -> 建造者
class ApiResponseBuilder<T>{
var code:Int = 0
var message:String?=null
var data:T?=null
var dataList:List<T>?=null
var extra:Any?=null
constructor(code: Int){
this.code = code
}
fun setMessage(message:String):ApiResponseBuilder<T>{
this.message = message
return this
}
fun setData(data:T):ApiResponseBuilder<T>{
this.data = data
return this
}
fun setDataList(dataList: List<T>):ApiResponseBuilder<T>{
this.dataList = dataList
return this
}
fun setExtra(extra:Any):ApiResponseBuilder<T>{
this.extra = extra
return this
}
fun build():ApiResponse<T>{
var response = ApiResponse(this)
// ......
return response
}
}
模拟消费
class ApiDone{
fun done(){
// 成功
val response1:ApiResponse<String> = ApiResponseBuilder<String>(200).setData("success").build()
val response2:ApiResponse<Int> = ApiResponseBuilder<Int>(200).setDataList(mutableListOf(1,2)).build()
//失败
val response3:ApiResponse<String> = ApiResponseBuilder<String>(404).setMessage("error").build()
}
}
适用环境
- 当需要使用具有长参数列表的构造函数或具有不同参数的构造函数列表时。
- 当需要构建同一对象的不同表现时。即当需要具有不同特征的同一类的对象。
总结
Builder 是一种设计模式,可让避免构造函数具有一长串参数,而并非所有参数都是必需的。以更灵活的方式构建某个对象的实例。 最后,这个模式最重要的不是它的具体实现,而是能够认识到这个模式可以解决的问题,以及什么时候可以应用。具体实现是最少的,因为这取决于所使用的编程语言