Fundamentals 8 min read

How the Flyweight Pattern Cuts Memory Use in Real‑World Java Services

The article explains the Flyweight design pattern, shows how a surge of 30 KB country objects caused memory pressure in a marketing service, and demonstrates a Java implementation with Flyweight, FlyweightFactory, and related code, while comparing it to Singleton and caching approaches.

IT Niuke
IT Niuke
IT Niuke
How the Flyweight Pattern Cuts Memory Use in Real‑World Java Services

The Flyweight pattern is used when a system creates a large number of duplicate objects; by caching and sharing these objects the memory footprint can be dramatically reduced.

It defines three typical roles: the Flyweight (the shared class that holds internal and external state) and the FlyweightFactory (responsible for creating and managing Flyweight instances).

Real‑world scenario

In a marketing service that builds landing pages, each request needed country and telephone‑code data. The raw data size was about 30KB per request, so every request allocated a new object that quickly became garbage, leading to out‑of‑memory alerts during a questionnaire push to all app users.

Data structure

The country metadata is stored as JSON, for example:

{
    "code": "US",
    "nameZh": "美国",
    "nameEn": "United States",
    "tel": "+1",
    "pyName": "mg",
    "sortNo": 1,
    "areaId": null
}

The overall container looks like:

{
  "allCountry": [],
  "commonCountry": [],
  "currentCountry": {}
}
allCountry

is immutable and represents the internal state (the largest memory consumer). commonCountry changes rarely and is treated as external state, while currentCountry is generated per request based on the client IP.

Code implementation

Country POJO:

@Data
public class Country {
    private String code;
    private String nameZh;
    private String nameEn;
    private String tel;
    private String pyName;
    private String sortNo;
    private Integer areaId;
}

Flyweight class holding the states:

@Getter
public class CountryList {
    // internal state
    private final List<Country> allCountry;
    // external state
    private List<Country> commonCountry;
    private Country currentCountry;

    public CountryList(List<Country> allCountry) {
        this.allCountry = allCountry;
    }

    public void setCommonCountry(List<Country> commonCountry) {
        this.commonCountry = commonCountry;
    }

    public void setCurrentCountry(Country currentCountry) {
        this.currentCountry = currentCountry;
    }
}

Factory that caches a single CountryList instance:

@Slf4j
@Component
@RequiredArgsConstructor
public class CountryListFactory {
    private static final String DEFAULT = "DEFAULT";
    private static final Map<String, CountryList> CL_MAP = Maps.newHashMap();

    private final CountryClient countryClient;

    @PostConstruct
    public void init() {
        final List<Country> countryList = countryClient.getCountryList();
        CL_MAP.put(DEFAULT, new CountryList(countryList));
    }

    public static CountryList getDefaultCl() {
        return CL_MAP.get(DEFAULT);
    }
}

The CountryClient simulates a Feign service that returns the full country list; its @PostConstruct method injects the data into the static map, making it available to the rest of the application.

Unit test

@SpringBootTest
class CountryListTest {

    @Test
    void testFactory() {
        final CountryList cl = CountryListFactory.getDefaultCl();
        assertNotNull(cl);
    }
}

Reflection

Singleton guarantees a single global instance; Flyweight guarantees shared instances that can be reused, so Singleton can be seen as a special case of Flyweight.

The primary goal of Flyweight is memory savings through sharing, whereas caching focuses on speeding up access.

Caching can be implemented using the Flyweight pattern.

Additional considerations

When Flyweight objects are accessed concurrently, thread‑safety must be addressed.

Alternative solutions (e.g., explicit caching, different data layouts) are possible; the pattern is chosen when the problem is identified first.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Design PatternsJavaMemory optimizationCachingSingletonFlyweight
IT Niuke
Written by

IT Niuke

Focused on IT technology sharing, original and innovative content. IT Niuke, we grow together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.