Photo by Johann Walter Bantz on Unsplash
The Flyweight design pattern is a structural design pattern commonly used when we want to group similar data for multiple objects. The primary intent of this pattern is to store common data for multiple objects in a single place and hence optimise for memory usage.
Let's understand this pattern by taking the case of a sneaker store 👟
Sneaker Store
Imagine running an online sneaker store. You've noticed that your customers always have a lot of questions and so, you've maintained every little detail about each pair of sneakers you have on display! 🗃
You have the following data points on every single pair:
- Name
- Size
- Color
- Brand
- Price
- Materials Used
- Description
- Sample Image
- laced
You soon realized that for a given type of pair, you're storing the same information again and again. Take the case of the Nike Air Force 1. For any two pairs, the only thing different is the size
and the color
. Everything else is duplicate information 😱
This definitely isn't the best way to store the details because it's super memory intensive ad costly. To solve this problem, you decide to create an object to store all the common details of the shoe and store only the size
, color
and a reference to the "common object" with every shoe instance.
If all of this is confusing, don't worry. Taking a look at the code should make things easier 😉
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)
}
Looking through the code written so far, we've created the details object for each type of shoe in our shop using a common struct. This way, we can add descriptions for more sneakers in the future 🤔
We've also created a map of the shoe type against the respective type. This way, every instance of the Sneaker
struct can easily access the corresponding details.
Also notice that our Sneaker
struct now only contains the size
, color
along with the shoeType
that allows us to fetch it's other details.
Let's see this in action
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())
}
This should give the following output:
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
That's about it for the Flyweight pattern! 😁
Note that one added benefit of this pattern (apart from memory efficiency) is also the fact that updating the common details, like price, for a type of sneaker would require you to make the change in only one place - the common details object as opposed to making the change in every individual instance of the sneaker
You can find all the code for this tutorial on this this github repo
Cheers ☕️
Top comments (0)