Flyweight pattern in Java

Introduction

Introducing the design patterns of [GoF](https://ja.wikipedia.org/wiki/Gang of for _ (Information Engineering)) ["Introduction to Design Patterns Learned in the Augmented and Revised Java Language"]( https://www.amazon.co.jp/ Supplementary Revised Edition Introduction to Design Patterns Learned in Java Language-Hiroshi Yuki / dp / 4797327030 / ref = pd_lpo_sbs_14_t_0? _ Encoding = UTF8 & psc = 1 & refRID = 2ZE4GPYNN55JGDR5QMHP I will summarize about.

Flyweight pattern

What is Flyweight

It is the "flyweight", which is a lightweight boxing class. The lightweight class means "lightness", which means that it consumes less memory. To create an object, you need to do new and allocate memory (instantiation), but if you create many objects, it will consume a lot of memory and the processing speed will be slow. To solve these problems, it is advisable to use it repeatedly for instances that have already been new. The pattern that suppresses memory consumption by sharing ** objects without newing as much as possible ** is called the ** Flyweight pattern **.

Character

The Flyweight pattern is used by the classes that appear in the class diagram below. image.png

Implementation class

Concrete example

As a concrete example, it will be explained based on the following class. image.png

Implementation class

-** Stamp class **

Stamp.java


package sample;

public class Stamp {
	//letter
	private char charname;
	//Number of times of use
	private int useCount = 0;
	//Number of generations
	private int newCount = 0;

	public int getUseCount() {
		return useCount;
	}

	public void setUseCount(int useCount) {
		this.useCount = useCount;
	}

	public int getNewCount() {
		return newCount;
	}

	public void setNewCount(int newCount) {
		this.newCount = newCount;
	}

	//constructor
	public Stamp(char charname) {
		this.charname = charname;
	}

	//Display characters
	public void print() {
		System.out.println("charname:" + this.charname);
	}
}

The Stamp class is a shared and used Flyweight class. It receives the character charname, is generated, and prints the character with the print method. Also, the number of uses (ʻuseCount) and the number of generations (newCount`) are provided with fields so that they can be easily understood, but they are not required.

-** StampFactory class **

StampFactory.java


package sample;

import java.util.HashMap;
import java.util.Map.Entry;

public class StampFactory {
	//Manage already generated Stamp instances
	private HashMap<String, Stamp> pool = new HashMap<>();
	//Singleton pattern
	private static StampFactory singleton = new StampFactory();

	//constructor
	private StampFactory() {
	}

	//Get a singleton instance
	public static StampFactory getInstance() {
		return singleton;
	}

	//Instantiation of Stamp(share)
	public synchronized Stamp getStamp(char charname) {
		//Key(letter)Value associated with(Stamp instance)To get
		Stamp bc = pool.get("" + charname);
		//Key(letter)Value associated with(Stamp instance)If could not be obtained
		if (bc == null) {
			//Create an instance of Stamp here
			bc = new Stamp(charname);
			//Count the number of new
			bc.setNewCount(bc.getNewCount() + 1);
			//Store in HashMap
			pool.put("" + charname, bc);
		}
		//Count the number of uses regardless of the presence or absence of new
		bc.setUseCount(bc.getUseCount() + 1);
		return bc;
	}

	//Output all Stamp instances managed by HashMap
	public void printAllPool() {
		for (Entry<String, Stamp> entry : pool.entrySet()) {
			System.out.println(
					entry.getKey() + " : " + entry.getValue().getUseCount() + " : " + entry.getValue().getNewCount());
		}
	}
}

This class serves as the FlayweightFactory, which is the factory that generates the Stamp class. It has a pool field as a Map for managing the generated instances and a singleton field that represents itself because it applies the Singleton pattern here. To use this class, first call the getInstance method from the outside to return the StampFactory instance that represents itself. Then, for the returned StampFactory instance, call the getStamp method with charname as an argument. If a Stamp instance with the charname passed as an argument as a key has already been created, it will be obtained from pool, but if the instance has not been created yet, an instance will be created and stored in pool. To do. Also, when an instance is created, +1 is added to newCount, and ʻuseCountis increased by +1 regardless of whether or not an instance is created, so that the number of times each Stamp instance is created and used is counted. In addition,printAllPool` is implemented as a method to output all Stamp instances stored in pool. The output content is "Key characters: Number of uses: Number of generations".

Execution class

-** Main class **

Main.java


package sample;

import java.util.ArrayList;

public class Main {
	public static void main(String[] args) {
		//Stamp instance preparation
		StampFactory factory = StampFactory.getInstance();
		ArrayList<Stamp> stamps = new ArrayList<>();
		stamps.add(factory.getStamp('a'));
		stamps.add(factory.getStamp('b'));
		stamps.add(factory.getStamp('c'));
		stamps.add(factory.getStamp('f'));
		stamps.add(factory.getStamp('e'));
		stamps.add(factory.getStamp('a'));
		stamps.add(factory.getStamp('b'));
		stamps.add(factory.getStamp('c'));
		stamps.add(factory.getStamp('d'));
		stamps.add(factory.getStamp('f'));
		stamps.add(factory.getStamp('a'));
		for (Stamp s : stamps) {
			s.print();
		}
		System.out.println("-------------------------------");
		System.out.println("charname : useCount : newCount");
		//Output all Stamp instances managed by HashMap
		factory.printAllPool();
	}
}

It is a class that serves as a Client that uses Flyweight and FlyweightFactory. By calling the getInstance method, which is a static method of the StampFactory class, to get the stampFactory instance, and calling the getStamp method for the obtained stampFactory instance, the stamp instance is stored in the pool field. Finally, by calling printAllPool (), all pool fields are output.

Execution result

The result of executing Main.java is as follows. Even for characters whose ʻuseCount is greater than 1, the newCount` is only once, indicating that the instance is being reused.

Execution result


charname:a
charname:b
charname:c
charname:f
charname:e
charname:a
charname:b
charname:c
charname:d
charname:f
charname:a
-------------------------------
charname : useCount : newCount
a : 3 : 1
b : 2 : 1
c : 2 : 1
d : 1 : 1
e : 1 : 1
f : 2 : 1

Advantages and disadvantages

By using the Flyweight pattern, you can reduce the number of times you renew an object and save memory. On the other hand, the disadvantage is that the objects stored in the pool are not subject to garbage collection and remain in memory, so it is necessary to manage them intentionally so as not to run out of memory.

Summary

You learned about the Flyweight pattern, which reduces memory consumption by sharing instances. The sample code is uploaded below, so please refer to it if you like.

-Flyweight sample code

In addition, other design patterns are summarized below, so please refer to them as well.

-[Updated from time to time] Summary of design patterns in Java

References

-[Introduction to Design Patterns Learned in the Augmented and Revised Java Language](https://www.amazon.co.jp/ Introduction to Design Patterns Learned in the Augmented and Revised Java Language-Hiroshi Yuki / dp / 4797327030 / ref = pd_lpo_sbs_14_t_0? _Encoding = UTF8 & psc = 1 & refRID = 2ZE4GPYNN55JGDR5QMHP)

Recommended Posts

Flyweight pattern in Java
Facade pattern in Java
Singleton pattern in Java
Observer pattern in Java
Iterator pattern in Java
Decorator pattern in Java
Prototype pattern in Java
Proxy pattern in Java
Template Method pattern in Java
Chain of Responsibility pattern in Java
Learn the design pattern "Flyweight" in Python
Singleton pattern in Python
Linux permissions in Java
Use DataFrame in Java
Visitor pattern in Python
Implement Table Driven Test in Java
Detect and process signals in Java.
Change the Flyweight pattern to Pythonic (?) (3)
Change the Flyweight pattern to Pythonic (?) (2)
Implement the Singleton pattern in Python
Change the Flyweight pattern to Pythonic (?) (1)
Implemented bubble sort in Java (BubbleSort)
GoF java design pattern rough summary
Overlapping regular expressions in Python and Java
Learn the design pattern "Prototype" in Python
Learn the design pattern "Builder" in Python
Learn the design pattern "Observer" in Python
Learn the design pattern "Memento" in Python
Learn the design pattern "Proxy" in Python
Express Python yield in JavaScript or Java
Apply Google Java Style formatter in IntelliJ
Learn the design pattern "Command" in Python
Differences in syntax between Python and Java
Get mail using Gmail API in Java
Learn the design pattern "Visitor" in Python
Learn the design pattern "Bridge" in Python
Learn the design pattern "Mediator" in Python
Learn the design pattern "Decorator" in Python
Learn the design pattern "Iterator" in Python
Learn the design pattern "Strategy" in Python
Learn the design pattern "Composite" in Python
Learn the design pattern "State" in Python
Let's run a Bash script in Java
Learn the design pattern "Adapter" in Python