The flyweight pattern is a design pattern I am not seeing that often in code bases but can be a good design pattern to reduce memory. The core idea is to initialize objects an share them as often as possible for reuse. Mostly the flyweight pattern can be seen in desktop UI implementation (GUI). In Java Swing, for instance, the JTable rendering uses this pattern, to reduce the computation needed for painting. String pools might use the pattern as well to reuse the expensive character arrays forming each string, among many other use cases.

There are some really good use cases for flyweight pattern in web applications. One of them I use regularly is for handling multiple connection pools, in which case a map is backing the pointer to the initialized connection pools. Another example is event logging, where the logger can call on events from a pool, and pass them to a message queue.

Implementation of flyweight pattern

A simple example of Golang flyweight pattern implementation:

...
//Color - struct holds color for reuse
type Color struct {
	Name  string
	Color *color.Color
}

var (
	pool map[string]*Color
	once sync.Once
)

func init() {
	once.Do(func() {
		pool = make(map[string]*Color)
	})
}

//NewColor - create a new instance
func NewColor(name string) *Color {
	switch name {
	case "red":
		return &Color{Name: name, Color: color.New(color.FgRed)}
	case "blue":
		return &Color{Name: name, Color: color.New(color.FgBlue)}
	case "green":
		return &Color{Name: name, Color: color.New(color.FgGreen)}
	case "yellow":
		return &Color{Name: name, Color: color.New(color.FgYellow)}
	case "cyan":
		return &Color{Name: name, Color: color.New(color.FgCyan)}
	default:
		return &Color{Name: name, Color: color.New(color.FgWhite)}
	}
}

//ColorFactory - get an instance from the initiaslized pool
func ColorFactory(name string) *Color {
	if v, ok := pool[name]; ok {
		return v
	}

	c := NewColor(name)
	pool[name] = c

	return c
}

//PrintColoredln - print colored line ( to add some functionality)
func (c *Color) PrintColoredln(ln string) {
	c.Color.Println(ln)
}

The above code generates color for CLI message painting and uses lazy initialization. On the initialization the map backing the color pool is empty and on request, it is filled up. This does not provide the best performance but does save some initial memory. On subsequent requests the already initialized Color is returned for use, so the memory footprint is reduced.

The benchmark for the code snippet clearly shows that the memory allocation is once off.

$ go test -bench=. -benchmem -benchtime=2s
BenchmarkFlyweight-4     	200000000	        12.7 ns/op	       0 B/op	       0 allocs/op
BenchmarkNewInstance-4   	20000000	       110 ns/op	      72 B/op	       3 allocs/op
PASS

 

Conclusion

The flyweight pattern in Golang, or any other language can reduce the memory footprint dramatically if similar objects are initialized often in the same runtime. There are many good use cases for the pattern in multiple layers on an n-Tier application, by reducing memory and CPU cycles.

The above code snippet can be found on GitHub. More information and examples on the Fylweight design pattern can be found on Wikipedia and for Java fans, Tutorialspoint has a good breakdown.

 

Share This