[Design mode] Flyweight mode, the guiding ideology of pool technology!

[Design mode] Flyweight mode, the guiding ideology of pool technology!

This is the 29th day that I participated in the Wenwen Challenge. For details of the event, please view: Wenwen Challenge


Design pattern catalog

What is Flyweight

concept

Flyweight Pattern is a structural pattern, which is mainly used to reduce the performance consumption of object creation and destruction to reduce memory usage . Object-oriented languages can bring a certain degree of flexibility and scalability to our development, and are more in line with people's way of thinking, but this will make our system create a lot of objects, which will reduce the performance of our system, so we can use A buffer pool is used to store these repeatedly used objects to reduce the number of repeated creation and destruction. The idea of the flyweight model is to reuse objects .

There are also many examples of the Flyweight model in our lives, such as the chess pieces of Go, the shared bicycle, and the swimming circle of the swimming pool. These things are used repeatedly. In development, we commonly use thread pools, String constant pools, and database connection pools. These are all "pools" established to avoid creating a lot of objects.

advantage

Reduce memory and improve performance. If we want to use an object, we only need to go to the "pool" to get it, and we don't need to create it again, which saves the system overhead of constant creation and destruction.

Disadvantage

Increase the complexity of the program. It is necessary to refine the granularity of objects and externalize the parts that cannot be shared to achieve sharing, which increases the complexity of coding and the difficulty of understanding the code.

in principle

"+" means compliance, "-" means non-compliance or irrelevance

in principleOpen and closedSingle responsibilityDimitRichter replacementDependency inversionInterface isolationComposite multiplexing
++--+-+

Applicable scene

  1. A large number of identical objects are required or there are many identical parts in a class of objects, and creating or destroying these objects will bring greater performance overhead. These objects can be extracted into a constant object, and then stored in the pool, and used directly when needed.
  2. The system does not rely on the state of these objects, just use them.
  3. An object can be divided into internal and external parts, the internal part can be used repeatedly, and the external part is defined by the user.

How to achieve

To realize the Flyweight model, the following five things are needed:

  1. Flyweight interface (Flyweight): defines the specifications to be implemented by all flyweight classes.
  2. Concrete Flyweight (Concrete Flyweight): implements the Flyweight interface.
  3. Unsharable Flyweight interface (Unsharable Flyweight): defines the specification to be implemented by non-shared weight classes.
  4. Concrete Unsharable Flyweight (Concrete Unsharable Flyweight): implements the interface of the Unsharable Flyweight.
  5. Flyweight Factory: Responsible for creating and managing flyweight objects.

Upper class diagram

It's a little bit complicated, you can understand it in combination with the following code.

Upload code

Huizhou is a tourist attraction (I speak for Huizhou). Honghua Lake is a very suitable place for cycling. Now there is a bike shop that rents out bicycles in Honghua Lake for tourists to ride around Honghua Lake. , FlyweightFactory specializes in providing bicycles. If there are not enough bicycles, they will buy new bicycles. Tourists (ConcreteUnsharableFlyweight) will return them to the bicycle shop after riding the bicycle.

/** * Flyweight mode test * Created on 2021/6/3. * * @author xuxiaobai */ public class FlyweightTest { public static void main (String[] args) { FlyweightFactory factory = new FlyweightFactory( 4 ); //Simulate ten people to pick up the car for ( int i = 0 ; i < 20 ; i++) { int finalI = i; new Thread(()->{ Flyweight flyweight = factory.getFlyweight(); flyweight.operate( new ConcreteUnsharableFlyweight( " " + finalI + " " )); try { //Happily riding a bicycle in Thread.sleep( 2000 ); } catch (InterruptedException e) { e.printStackTrace(); } //Return after riding flyweight.release(); }).start(); } try { //Sleep for five seconds and let the thread finish Thread.sleep( 20000 ); } catch (InterruptedException e) { } System.out.println( "The number of bicycles in the factory:" +factory.getFlyweightSize()); /** * Result: * Current id:1 is occupied * Successfully unlocked! * Current id: 2 is occupied * Successfully unlocked! * Current bicycle id: 1 Current bicycle id: 2 Xiaoming No. 1 Cycling * Xiao Ming No. 0 Cycling * Current id: 3 is occupied * Successfully unlocked! * Current bicycle id: 3 Xiaoming No. 2 Cycling * There are no free bicycles, please wait * There are no free bicycles, please wait * Current id: 3 is occupied * Successfully unlocked! * Current bicycle id: 3 Xiaoming No. 4 Cycling * There are no free bicycles, please wait * Current bicycle id: 3 Xiaoming No. 5 Cycling * There are no free bicycles, please wait * Current id: 4 is occupied * Successfully unlocked! * Current bicycle id: 4 Xiaoming No. 19 Cycling * There are no free bicycles, please wait * Current bicycle id: 4 Xiaoming No. 3 Cycling * There are no free bicycles, please wait * Current id: 5 is occupied * Successfully unlocked! * Current bicycle id: 5 Xiaoming 17 Cycling * There are no free bicycles, please wait * Current bicycle id: 5 Xiaoming No. 18 Cycling * Current id: 1 has been returned * Current id: 3 has been returned * Current id: 2 has been returned * Current id:1 is occupied * Successfully unlocked! * Current bicycle id: 1 Xiaoming No.15 bicycle * Current id: 2 is occupied * Successfully unlocked! * Current bicycle id: 2 Xiaoming No. 16 Cycling * Current id: 3 is occupied * Successfully unlocked! * Current bicycle id: 3 Xiaoming Bicycle No. 14 * There are no free bicycles, please wait * Current id: 3 has been returned * Current id: 3 has been returned * Current id: 3 is occupied * Successfully unlocked! * There are no free bicycles, please wait * Current bicycle id: 3 Xiaoming No. 13 Cycling * Current id: 4 has been returned * Current id: 4 has been returned * Current id: 4 is occupied * Successfully unlocked! * Current bicycle id: 4 Xiaoming No.12 Cycling * There are no free bicycles, please wait * Current id: 5 has been returned * Current id: 5 has been returned * Current id: 5 is occupied * Successfully unlocked! * There are no free bicycles, please wait * Current bicycle id: 5 Xiaoming No. 11 Cycling * Current id: 1 has been returned * Current id: 3 has been returned * Current id: 2 has been returned * Current id:1 is occupied * Successfully unlocked! * Current id: 2 is occupied * Successfully unlocked! * Current bicycle id: 2 Xiaoming No. 9 Cycling * Current id: 3 is occupied * Successfully unlocked! * Current bicycle id: 3 Xiaoming No. 8 Cycling * There are no free bicycles, please wait * Current bicycle id: 1 Xiaoming No. 10 bicycle * Current id: 3 has been returned * Current id: 3 is occupied * Successfully unlocked! * There are no free bicycles, please wait * Current bicycle id: 3 Xiaoming No. 7 Cycling * Current id: 4 has been returned * Current id: 4 is occupied * Successfully unlocked! * Current bicycle id: 4 Xiaoming No. 6 Cycling * Current id: 5 has been returned * Current id: 3 has been returned * Current id: 1 has been returned * Current id: 2 has been returned * Current id: 3 has been returned * Current id: 4 has been returned * Number of bicycles in the factory: 6 */ } } /** * Flyweight factory class * Simulation car shop */ class FlyweightFactory { private List<Flyweight> flyweights = new ArrayList(); private int flyweightSize = 0 ; public FlyweightFactory ( int num) { for ( int i = 1 ; i <num; i++) { flyweights.add( new ConcreteFlyweight(i)); flyweightSize++; } } /** * Only one person can come to pick up the bike at a time * @return */ public synchronized Flyweight getFlyweight () { Flyweight flyweight1 = getOneFlyweight(); if (flyweight1 != null ) return flyweight1; try { //Simulate waiting Thread.sleep( 500 ); } catch (InterruptedException e) { } //Let s see if there are any cars coming back flyweight1 = getOneFlyweight(); if (flyweight1 != null ) return flyweight1; //I really didn t wait, buy a new car return newFlyweight(); } /** * Go buy a new bicycle * @return */ private synchronized Flyweight newFlyweight () { ConcreteFlyweight flyweight = new ConcreteFlyweight( this .flyweightSize); flyweightSize++; flyweights.add(flyweight); return flyweight; } /** * Find a car inside the car shop * @return */ private Flyweight getOneFlyweight () { Iterator<Flyweight> iterator = flyweights.iterator(); while (iterator.hasNext()){ Flyweight flyweight = iterator.next(); if (flyweight.occupy()) { System.out.println( "Unlock successfully!" ); return flyweight; } } System.out.println( "There are no free bicycles, please wait a moment" ); return null ; } public int getFlyweightSize () { return flyweightSize; } } /** * Specific Flyweight Class * Simulated bicycles */ class ConcreteFlyweight implements Flyweight { private int id; UnsharableFlyweight unsharableFlyweight; //0 is idle, 1 is occupied private volatile int state = 0 ; public ConcreteFlyweight ( int id) { this .id = id; } /** * Cycling * @param unsharableFlyweight */ @Override public synchronized void operate (UnsharableFlyweight unsharableFlyweight) { System.out.print( "Current bicycle id:" +id+ "" ); unsharableFlyweight.operate(); } /** * Occupation * * @return true: successful occupation, false occupation failed */ @Override public synchronized boolean occupy () { if (state == 0 ) { state = 1 ; System.out.println( "Current id:" + id + "occupied" ); return true ; } return false ; } /** * Release/Return */ @Override public synchronized void release () { System.out.println( "Current id:" + id + " Returned " ); this .state = 0 ; } } /** * Flyweight class interface * Simulation car */ interface Flyweight { void operate (UnsharableFlyweight unsharableFlyweight) ; void release () ; boolean occupy () ; } /** * Specific non-Flyweight classes * Simulate a cyclist */ class ConcreteUnsharableFlyweight implements UnsharableFlyweight { private String name; public ConcreteUnsharableFlyweight (String name) { this .name=name; } @Override public void operate () { System.out.println(name+ "cycling" ); } } /** * Non-Flyweight Class Interface */ interface UnsharableFlyweight { void operate () ; } Copy code

There are nearly two hundred lines of code here, and a lot of comments have been added. There is no credit and hard work. I hope you can give me a praise for my hard work.

summary

The focus of the Flyweight model is to share and reuse objects , store fine-grained objects, and apply them directly next time. There is no need to create them again, which avoids the cost of creating a large number of similar objects, thereby improving System performance. Many pool technologies are based on the flyweight model, but the flyweight model is not applicable everywhere. It can only be used when a large number of objects of each type are created and the system does not rely on the state of these objects. .

The Flyweight model is very similar to the Singleton model. I once doubted whether the Flyweight model should be included in the creation model. After I have finished studying now, I found that my suspicion was wrong. Flyweight mode should be a structural mode, it is managing a group of objects, this group of objects and the management class are combined together, and the focus is on the structure of the object. The singleton mode is to focus on whether the object of this class is single , to ensure that there is only one object for each class, while the Flyweight mode is to save memory and improve performance . It does not guarantee that there is only one object for each class. Once the object is not enough, Will create a new one.

The more you know, the more you don't know.

If there is a problem with the content of this article, please comment directly or send me a private message. If you think I ve written pretty well, just like it is to support me.

Without permission, shall not be reproduced!