Facilitates the reuse of many fine grained objects, making the utilization of large numbers of objects more efficient.
提高对象的重用率,减少大量重复对象在内存中的创建开销和资源占用开销
享元模式中提出了两个重要的概念,内部状态intrinsic和外部状态extrinsic。
内部状态是可以被共享的,外部状态是不可以被共享的,外部状态的数据应该是被传入的。
上面两句话可能有些拗口,很多时候享元模式都会以在线游戏来举例。游戏中一些角色,在外观上是一样的,拥有相同的外形外形,这就是其内部状态,在内存中可以只需要一份,这样来实现了数据的共享;而这种游戏角色会在地图上不同的地方多次出现,出现的位置、血量、其他数值会有差异,这就是外部状态,需要在内存中维护多份来体现差异。
- 尽可能实现对象复用,降低内存开销。
- 因为对象复用,也减低了重新创建对象的性能开销。
- 某电子商务系统会发送消息提醒给客户以告知信息,不同类型的消息套用不同的模版,模版的数量有多种,下面列举几种以举例。
模版1
感谢你的支持, 你购买的商品<<ProductName>>, 订单号<<OrderNo>>,已经发货, 快递单号为<<TrackNo>>
模版2
客户你好, 你关注的商品<<ProductName>>, 正在促销打折! 数量不多!
模版3
客户你好, 我们已经你对订单<<OrderNo>>的评价, 感谢!
-
当需要给客户发送信息时候,只需要调用正确的模版然后套用相关数据发送信息即可。
-
代码示例
message 结构体是不可共享的外部状态,是消息的变化的内容。
type Message struct {
ProductName string
OrderNo string
TrackNo string
TemplateNo int
}
func (m *Message) Merge(MessageTemplate string) string {
message := strings.ReplaceAll(MessageTemplate, "<<ProductName>>", m.ProductName)
message = strings.ReplaceAll(message, "<<OrderNo>>", m.OrderNo)
message = strings.ReplaceAll(message, "<<TrackNo>>", m.TrackNo)
return message
}
全局变量F充当缓存作用,缓存所有可以共享的内部状态,也就是消息的模板,当缓存中没有模板存在的时候,就调用QueryByNo函数去数据库查,这里也可以看到,缓存模板也减少了请求数据的开销,这正是享元模式的意义所在。
var F = make(map[int]*string)
func GetMsgTemplate(templateNo int) string {
msgTemplateBody := F[templateNo]
if msgTemplateBody == nil {
//模拟去数据库查询
messageBody := QueryByNo(templateNo)
F[templateNo] = &messageBody
msgTemplateBody = &messageBody
}
return *msgTemplateBody
}
模拟执行
message1 := Message{"三星手机", "4884741244", "8514484122", 1}
message2 := Message{"华为手机", "1211223122", "3221234133", 2}
message3 := Message{"oppo手机", "7656754133", "9556435133", 3}
message4 := Message{"小米手机", "8976897144", "8477474413", 1}
message5 := Message{"荣耀手机", "5437659433", "0000211133", 1}
message6 := Message{"格力空调", "7656223133", "0056423323", 3}
message7 := Message{"长虹冰箱", "7623323133", "0056435133", 3}
message8 := Message{"格兰仕微波炉", "72533878122", "5452321133", 3}
fmt.Println(message1.Merge(GetMsgTemplate(message1.TemplateNo)))
fmt.Println(message2.Merge(GetMsgTemplate(message2.TemplateNo)))
fmt.Println(message3.Merge(GetMsgTemplate(message3.TemplateNo)))
fmt.Println(message4.Merge(GetMsgTemplate(message4.TemplateNo)))
fmt.Println(message5.Merge(GetMsgTemplate(message5.TemplateNo)))
fmt.Println(message6.Merge(GetMsgTemplate(message6.TemplateNo)))
fmt.Println(message7.Merge(GetMsgTemplate(message7.TemplateNo)))
fmt.Println(message8.Merge(GetMsgTemplate(message8.TemplateNo)))
fmt.Println("缓存的模版数量:", len(F))
结果
感谢你的支持, 你购买的商品三星手机, 订单号4884741244,已经发货, 快递单号为8514484122
客户你好, 你关注的商品华为手机, 正在促销打折! 数量不多!
客户你好, 我们已经你对订单7656754133的评价, 感谢!
感谢你的支持, 你购买的商品小米手机, 订单号8976897144,已经发货, 快递单号为8477474413
感谢你的支持, 你购买的商品荣耀手机, 订单号5437659433,已经发货, 快递单号为0000211133
客户你好, 我们已经你对订单7656223133的评价, 感谢!
客户你好, 我们已经你对订单7623323133的评价, 感谢!
客户你好, 我们已经你对订单72533878122的评价, 感谢!
缓存的模版数量: 3
从上面的输出结果来看,内存中只保存了3分模板,减少了内存的开销。