Flyweight pattern in Go design pattern

Yuxian: CSDN content partner, CSDN new star mentor, 51CTO (Top celebrity + expert blogger), github open source enthusiast (secondary development of go-zero source code, game back-end architecture https://github.com/Peakchen)

 

Detailed explanation of the principle of Flyweight Pattern:
Flyweight Pattern is a structural design pattern used to effectively support the sharing of a large number of fine-grained objects. Flyweight mode reduces memory usage and improves performance by sharing objects.

The core idea of ​​Flyweight pattern is to divide objects into shareable internal state (Intrinsic State) and non-shareable external state (Extrinsic State). The internal state is a fixed part of the object and can be shared by multiple objects; the external state is the changing part of the object, and each object has its own external state.

The key to the Flyweight pattern is the shared object. When a new object needs to be created, it is first checked whether an object with the same internal state already exists. If it exists, return the existing object directly; if not, create a new object and add it to the shared pool for later use.

By sharing objects, the Flyweight pattern can significantly reduce memory usage, especially when a large number of similar objects are required. It is suitable for situations where a large number of fine-grained objects need to be created, and there is a lot of shared state between objects.

Underlying structure diagram:
The following is a classic structure diagram of the Flyweight mode:

+----------------------------+
|          Client            |
+----------------------------+
| - externalState          |
| + Operation()               |
+----------------------------+

        ^
        |
        |
        |
        |
        v

+----------------------------+
|         Flyweight         |
+----------------------------+
| + Operation(externalState) |
+----------------------------+

        ^
        |
        |
        |
        |
        v

+----------------------------+
|    ConcreteFlyweight  |
+----------------------------+
| + Operation(externalState) |
+----------------------------+

In the above structural diagram, Client it is the client, which  Operation() operates the flyweight object by calling methods.

Flyweight It is the Flyweight interface, which defines the methods for manipulating Flyweight objects.

ConcreteFlyweight It is a specific flyweight, which implements  Operation() the method of flyweight interface and contains internal state.

Scenario Explanation:
Flyweight mode is applicable to the following scenarios:

  1. The Flyweight pattern can be used when a large number of fine-grained objects need to be created, and these objects can share some or all of the state. By sharing objects, you can reduce memory usage and improve performance.
  2. The Flyweight pattern can be used when most of the object's state can be replaced by external state. External state can be dynamically passed to flyweight objects at runtime, avoiding creating a large number of objects with the same internal state.

Code example implementation:
The following is an example of Flyweight mode implemented in Go language:

package main

import "fmt"

// Flyweight 享元接口
type Flyweight interface {
	Operation(externalState string)
}

// ConcreteFlyweight 具体享元
type ConcreteFlyweight struct {
	internalState string
}

// Operation 操作享元对象
func (f *ConcreteFlyweight) Operation(externalState string) {
	fmt.Printf("Internal state: %s, External state: %s\n", f.internalState, externalState)
}

// FlyweightFactory 享元工厂
type FlyweightFactory struct {
	flyweights map[string]Flyweight
}

// GetFlyweight 获取享元对象
func (ff *FlyweightFactory) GetFlyweight(key string) Flyweight {
	if flyweight, ok := ff.flyweights[key]; ok {
		return flyweight
	}

	flyweight := &ConcreteFlyweight{internalState: key}
	ff.flyweights[key] = flyweight
	return flyweight
}

func main() {
	factory := &FlyweightFactory{
		flyweights: make(map[string]Flyweight),
	}

	flyweight1 := factory.GetFlyweight("key1")
	flyweight1.Operation("state1")

	flyweight2 := factory.GetFlyweight("key2")
	flyweight2.Operation("state2")

	flyweight3 := factory.GetFlyweight("key1")
	flyweight3.Operation("state3")
}

In the above example, we defined the flyweight interface ( Flyweight) and the concrete flyweight ( ConcreteFlyweight). The Flyweight interface defines methods for manipulating Flyweight objects, and the specific Flyweight implements this interface and contains internal states. The flyweight factory ( FlyweightFactory) is responsible for creating and managing flyweight objects.

In  main the function, we obtain the flyweight object through the flyweight factory, and call its  Operation methods to operate the object. Note that when the same internal state is obtained, the factory will return the same flyweight object, realizing the sharing of objects.

Links to Documentation:
Here are some links to references about the Flyweight pattern:

  • Design Patterns: Elements of Reusable Object-Oriented Software ("Design Patterns: The Foundation of Reusable Object-Oriented Software") - GoF (Gang of Four) book: link
  • Flyweight Design Pattern - GeeksforGeeks: 链接
  • Flyweight Design Pattern - TutorialsPoint:  link
  • Flyweight Design Pattern - Refactoring Guru:  link

Which products are currently in use:
Flyweight pattern is a commonly used design pattern, which is used by many software and frameworks. Here are some examples of products and tools that use the Flyweight pattern:

  1. Classes in Java String: StringClasses are immutable and when multiple strings with the same value are created, they share the same object in the string constant pool.
  2. Database connection pool: In the database connection pool, connection objects are heavyweight resources. By using the Flyweight mode, connection objects can be shared and reused, reducing the overhead of creating and destroying connections.
  3. Graphics library and game engine: In graphics library and game engine, graphics objects and particle objects are usually fine-grained, and flyweight mode can be used to share and reuse these objects to improve performance.

Guess you like

Origin blog.csdn.net/feng1790291543/article/details/132159630