Introduction
The flyweight pattern is a pattern that helps minimize memory usage by sharing and reusing data. A common example is wordprocessor where each character not only holds the character like ‘A’ but also things like markup and formatting data. Instead of having each element of a document carry all this data, this markup and formatting data is stored using flyweight patterns, to which the elements refer. This method saves a lot of memory.
So, flyweight objects can have:
- Intrinsic state: invariant and shareable, but also context independent (like aformentioned character ‘A’)
- Extrinsic state: that could be the position of the character in the document.
So, what does it look like? Well, a very simple version is this:

Implementation in Go
Open a commandline or terminal in an empty directory and type:
go mod init flyweight_pattern
Now open your favourite IDE and add a main.go file.
Start with the following:
package main
import (
"fmt"
)
The flyweight interface
Now we will define the Flyweight interface:
type Character interface {
Display(row, col int) // extrinsic state passed as parameters
}
This code defines the Character interface which defines a contract for displayomh characters at specific positions. The Display() method takes row and column parameter, which represents the extrinisic state. This state will be passed in from external context rather than stored within the flyweight objects themselves.
The concrete implementation
The ConcreteCharacter struct is our actual flyweight implementation, as it contains only the symbol field as its intrinsic state. Why only the symbol? By storing the unchanging symbol, and excluding extrinsic data like the row and column multiple references can safely share the same instance. The Display() method combines extrinsic and intrinisc state to produce the desired output:
type ConcreteCharacter struct {
symbol rune
}
func (c *ConcreteCharacter) Display(row, col int) {
fmt.Printf("Character '%c' at position (%d, %d)\n", c.symbol, row, col)
}
The flyweight factory
Now we come to the CharacterFactory which will act as the central management system for the flyweight instances, maintaining a map associating each symbol with its corresponding flyweight object. The GetCharacter() method implements the core flyweight logic. It first checks if a flyweight object for the requested symbol has already been created. If it does it returns the this object, if not it stores this object it creates and stores one, and returns it:
type CharacterFactory struct {
characters map[rune]*ConcreteCharacter
}
func NewCharacterFactory() *CharacterFactory {
return &CharacterFactory{
characters: make(map[rune]*ConcreteCharacter),
}
}
func (f *CharacterFactory) GetCharacter(symbol rune) *ConcreteCharacter {
if char, exists := f.characters[symbol]; exists {
fmt.Printf("Reusing existing flyweight for '%c'\n", symbol)
return char
}
fmt.Printf("Creating new flyweight for '%c'\n", symbol)
char := &ConcreteCharacter{symbol: symbol}
f.characters[symbol] = char
return char
}
func (f *CharacterFactory) GetCreatedFlyweightsCount() int {
return len(f.characters)
}
Testing time
Now we can test our setup:
func main() {
factory := NewCharacterFactory()
char1 := factory.GetCharacter('A')
char2 := factory.GetCharacter('B')
char3 := factory.GetCharacter('A') // Reuses existing flyweight
char4 := factory.GetCharacter('A') // Reuses existing flyweight
char1.Display(1, 1)
char2.Display(1, 2)
char3.Display(2, 1)
char4.Display(3, 1)
fmt.Printf("\nTotal flyweights created: %d\n", factory.GetCreatedFlyweightsCount())
fmt.Printf("Total character references: 4\n")
fmt.Printf("Memory saved by sharing flyweights!\n")
}
This function demonstrates the pattern’s effectiveness: it creates four character references but it generates only two flyweight objects. As you can see, it displays the characters at different positions using the extrinisic state.
Conclusion
The Flyweight pattern is all about working smarter, not harder. Instead of creating a mountain of identical objects, you reuse what you already have and just plug in the bits that change. In our Go example, we only made two flyweights but displayed four characters — not bad for a few lines of code!
It’s the kind of pattern that quietly does its job behind the scenes, saving memory and keeping things snappy. Whether you’re building a game, a text editor, or just like writing efficient code, the Flyweight pattern is a neat trick to keep in your developer toolbox.
- Make the flyweightfactory threadsafe.
- Use generics to make the whole pattern more flexible.




