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.
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": {}
} allCountryis 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
IT Niuke
Focused on IT technology sharing, original and innovative content. IT Niuke, we grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
