设计模式:享元模式⚖️

2025-06-07

设计模式:享元模式⚖️

照片由Johann Walter BantzUnsplash上拍摄

享元设计模式是一种结构化设计模式,通常用于将多个对象的相似数据分组。该模式的主要目的是将多个对象的公共数据存储在一个地方,从而优化内存使用。

让我们以运动鞋商店为例来理解这种模式👟

运动鞋店

想象一下,你经营着一家线上运动鞋店。你注意到顾客总是有很多疑问,所以你精心维护着每双运动鞋的每一个细节!🗃

对都有以下数据点

  • 姓名
  • 尺寸
  • 颜色
  • 品牌
  • 价格
  • 使用的材料
  • 描述
  • 示例图像
  • 带花边的

你很快就会意识到,对于某一类型的鞋子,你一遍又一遍地存储着相同的信息。以 Nike Air Force 1 为例。对于任何两双鞋,唯一不同的就是sizecolor。其他一切都是重复信息 😱

这绝对不是存储细节的最佳方式,因为它非常耗费内存,而且成本高昂。为了解决这个问题,你决定创建一个对象来存储鞋子的所有通用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,
}
Enter fullscreen mode Exit fullscreen mode
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]
}
Enter fullscreen mode Exit fullscreen mode
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)
}
Enter fullscreen mode Exit fullscreen mode

回顾目前为止编写的代码,我们使用一个通用的结构体为商店中每种类型的鞋子创建了详细信息对象。这样,我们将来可以为更多运动鞋添加描述 🤔

我们还创建了鞋子类型与相应类型的映射。这样,Sneaker结构体的每个实例都可以轻松访问相应的详细信息。

还要注意,我们的Sneaker结构现在只包含sizecolor以及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())
}
Enter fullscreen mode Exit fullscreen mode

这应该给出以下输出:

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
Enter fullscreen mode Exit fullscreen mode

这就是 Flyweight 模式的全部内容!😁

请注意,这种模式的另一个好处(除了内存效率之外)是,更新某种运动鞋的常见细节(如价格)只需要在一个地方进行更改 - 常见细节对象,而不是在运动鞋的每个单独实例中进行更改

您可以在此 GitHub 仓库中找到本教程的所有代码

干杯☕️

文章来源:https://dev.to/shubhamzanwar/design-patterns-flyweight-pattern-27a1
PREV
使用 Rust 构建一个简单的 Web 服务器
NEXT
JWT(JSON Web Token) JWT 用于什么?