设计模式:享元模式⚖️
照片由Johann Walter Bantz在Unsplash上拍摄
享元设计模式是一种结构化设计模式,通常用于将多个对象的相似数据分组。该模式的主要目的是将多个对象的公共数据存储在一个地方,从而优化内存使用。
让我们以运动鞋商店为例来理解这种模式👟
运动鞋店
想象一下,你经营着一家线上运动鞋店。你注意到顾客总是有很多疑问,所以你精心维护着每双运动鞋的每一个细节!🗃
每对都有以下数据点:
- 姓名
- 尺寸
- 颜色
- 品牌
- 价格
- 使用的材料
- 描述
- 示例图像
- 带花边的
你很快就会意识到,对于某一类型的鞋子,你一遍又一遍地存储着相同的信息。以 Nike Air Force 1 为例。对于任何两双鞋,唯一不同的就是size
和color
。其他一切都是重复信息 😱
这绝对不是存储细节的最佳方式,因为它非常耗费内存,而且成本高昂。为了解决这个问题,你决定创建一个对象来存储鞋子的所有通用size
细节,并且只存储,color
以及每个鞋子实例对“通用对象”的引用。
如果这一切让你感到困惑,别担心。看看代码应该会让事情变得更容易。
type SneakerDetails struct {
name string
brand string
price float64
materials []string
description string
image string
laced bool
}
var NikeAirForceDetails = SneakerDetails{
name: "Nike Air Force 1",
brand: "Nike",
price: 144.99,
materials: []string{"leather", "rubber"},
description: "Originally released in 1982, the Nike Air Force 1 was the first Nike model to feature Air technology.",
image: "https://via.placeholder.com/50",
laced: true,
}
var AdidasSuperstarDetails = SneakerDetails{
name: "Adidas Superstar",
brand: "Adidas",
price: 85.99,
materials: []string{"leather", "rubber"},
description: "Originally made for basketball courts in the '70s.",
image: "https://via.placeholder.com/50",
laced: true,
}
const (
NikeAirForce = "Nike Air Force 1"
AdidasSuperstar = "Adidas Superstar"
)
var DetailsMap = map[string]SneakerDetails{
NikeAirForce: NikeAirForceDetails,
AdidasSuperstar: AdidasSuperstarDetails,
}
func getShoeDetails(shoeType string) SneakerDetails {
return DetailsMap[shoeType]
}
type Sneaker struct {
shoeType string
size int
color string
}
func (s *Sneaker) describe() string {
details := getShoeDetails(s.shoeType)
return fmt.Sprintf("The %s is of size %d, color %s and costs %.2f. The Manufacturer is %s", details.name, s.size, s.color, details.price, details.brand)
}
回顾目前为止编写的代码,我们使用一个通用的结构体为商店中每种类型的鞋子创建了详细信息对象。这样,我们将来可以为更多运动鞋添加描述 🤔
我们还创建了鞋子类型与相应类型的映射。这样,Sneaker
结构体的每个实例都可以轻松访问相应的详细信息。
还要注意,我们的Sneaker
结构现在只包含size
,color
以及shoeType
允许我们获取其其他详细信息的。
让我们看看实际效果
func main() {
sneaker1 := Sneaker{
shoeType: NikeAirForce,
size: 9,
color: "white",
}
sneaker2 := Sneaker{
shoeType: AdidasSuperstar,
size: 8,
color: "black",
}
fmt.Println(sneaker1.describe())
fmt.Println(sneaker2.describe())
}
这应该给出以下输出:
The Nike Air Force 1 is of size 9, color white and costs 144.99. The Manufacturer is Nike
The Adidas Superstar is of size 8, color black and costs 85.99. The Manufacturer is Adidas
这就是 Flyweight 模式的全部内容!😁
请注意,这种模式的另一个好处(除了内存效率之外)是,更新某种运动鞋的常见细节(如价格)只需要在一个地方进行更改 - 常见细节对象,而不是在运动鞋的每个单独实例中进行更改
您可以在此 GitHub 仓库中找到本教程的所有代码
干杯☕️
文章来源:https://dev.to/shubhamzanwar/design-patterns-flyweight-pattern-27a1