What is Flyweight
concept
Flyweight Pattern is a structural pattern, which is mainly used to reduce the performance consumption of object creation and destruction, so as to reduce the occupation of memory. Object oriented language can bring some flexibility and expansibility to our development, and it is more in line with people's way of thinking, but it will make our system create many objects, which will degrade the performance of our system. Therefore, we can use a buffer pool to store these repeatedly used objects and reduce the number of repeated creation and destruction, The idea of meta pattern is to reuse objects.
There are also many examples of Yuan sharing mode in our life. For example, the chess pieces of go, sharing bicycles, and the swimming circle of the swimming pool are used repeatedly. In development, we often use thread pool, String constant pool and database connection pool to avoid creating many objects.
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-yvexshsd-163318128589)( https://gitee.com/xuxiaojian1999/image-bed/raw/master/img/%E7%BE%8E%E5%A5%B3%E6%B8%B8%E6%B3%B3.gif )]
advantage
Reduce memory and improve performance. If we want to use an object, we just need to get it from the "pool", and we don't need to create it again, which saves the system overhead of continuous creation and destruction.
shortcoming
Increase program complexity. It is necessary to refine the granularity of objects and externalize the parts that cannot be shared to realize sharing, which increases the complexity of coding and the difficulty of understanding the code.
principle
"+" means compliance, "-" means non-compliance or irrelevant
principle | Open and closed | Single responsibility | Dimitt | Richter substitution | Dependency inversion | Interface isolation | Synthetic multiplexing |
---|---|---|---|---|---|---|---|
+ | + | - | - | + | - | + | |
Applicable scenario
- It requires a large number of the same objects or many of the same parts in a class of objects, and creating or destroying these objects will bring a large performance overhead. These objects can be extracted into a constant object, and then stored in the pool, which can be directly used when it needs to be applied.
- The system does not depend on the state of these objects, but only for use.
- 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 realize the yuan sharing mode, you need the following five things:
- Flyweight: defines the specifications to be implemented by all shared metaclasses.
- Concrete Flyweight: implements the Concrete Flyweight interface.
- Unshareable flyweight: defines the specification to be implemented by the unshareable flyweight.
- Concrete unsharable flyweight: implements the unsharable flyweight interface.
- Flyweight Factory: responsible for creating and managing the Flyweight Factory objects.
Upper class graph
It is a little bit complex, which can be understood in combination with the following code.
Upper code
Huizhou is a tourist attraction (I speak for Huizhou). Honghua lake is a very suitable place for cycling. Now there is a car shop that rents bicycles in Honghua lake for tourists to ride around Honghua lake. Flyweight factory specially provides a single car. If there are not enough bicycles, they will buy new bicycles. Tourists (concrete unsharable flyweight) After riding the bike, it will be returned to the car store.
/** * Meta 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("Xiao Ming"+ finalI +"number")); try { //Ride a bike happily Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //Return after riding flyweight.release(); }).start(); } try { //Sleep for five seconds and let the thread run Thread.sleep(20000); } catch (InterruptedException e) { } System.out.println("Number of single cars in the factory:"+factory.getFlyweightSize()); /** * result: * Current id:1 occupied * Unlock successfully! * Current id:2 occupied * Unlock successfully! * Current bicycle id:1 current bicycle id:2 Xiaoming No. 1 cycling * Xiaoming No. 0 cycling * Current id:3 occupied * Unlock successfully! * Current bike id:3 Xiaoming No. 2 cycling * There are no free bicycles, please wait a moment * There are no free bicycles, please wait a moment * Current id:3 occupied * Unlock successfully! * Current bike id:3 Xiaoming No. 4 cycling * There are no free bicycles, please wait a moment * Current bike id:3 Xiaoming No. 5 cycling * There are no free bicycles, please wait a moment * Current id:4 occupied * Unlock successfully! * Current bike id:4 Xiaoming No. 19 cycling * There are no free bicycles, please wait a moment * Current bike id:4 Xiaoming No. 3 cycling * There are no free bicycles, please wait a moment * Current id:5 occupied * Unlock successfully! * Current bike id:5 Xiaoming riding a bike on the 17th * There are no free bicycles, please wait a moment * Current bike id:5 Xiaoming cycling on the 18th * Current id:1 returned * Current id:3 returned * Current id:2 returned * Current id:1 occupied * Unlock successfully! * Current bike id:1 Xiaoming cycling on the 15th * Current id:2 occupied * Unlock successfully! * Current bike id:2 Xiaoming riding a bike on the 16th * Current id:3 occupied * Unlock successfully! * Current bike id:3 Xiaoming cycling on the 14th * There are no free bicycles, please wait a moment * Current id:3 returned * Current id:3 returned * Current id:3 occupied * Unlock successfully! * There are no free bicycles, please wait a moment * Current bike id:3 Xiaoming No. 13 cycling * Current id:4 returned * Current id:4 returned * Current id:4 occupied * Unlock successfully! * Current bike id:4 Xiaoming cycling on the 12th * There are no free bicycles, please wait a moment * Current id:5 returned * Current id:5 returned * Current id:5 occupied * Unlock successfully! * There are no free bicycles, please wait a moment * Current bike id:5 Xiaoming cycling on the 11th * Current id:1 returned * Current id:3 returned * Current id:2 returned * Current id:1 occupied * Unlock successfully! * Current id:2 occupied * Unlock successfully! * Current bike id:2 Xiaoming No. 9 cycling * Current id:3 occupied * Unlock successfully! * Current bike id:3 Xiaoming No. 8 cycling * There are no free bicycles, please wait a moment * Current bike id:1 Xiaoming No. 10 cycling * Current id:3 returned * Current id:3 occupied * Unlock successfully! * There are no free bicycles, please wait a moment * Current bike id:3 Xiaoming No. 7 cycling * Current id:4 returned * Current id:4 occupied * Unlock successfully! * Current bike id:4 Xiaoming No. 6 cycling * Current id:5 returned * Current id:3 returned * Current id:1 returned * Current id:2 returned * Current id:3 returned * Current id:4 returned * Number of single cars in the factory: 6 */ } } /** * Xiangyuan factory * Simulated 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 pick up the bike at a time * @return */ public synchronized Flyweight getFlyweight() { Flyweight flyweight1 = getOneFlyweight(); if (flyweight1 != null) return flyweight1; try { //Simulated waiting Thread.sleep(500); } catch (InterruptedException e) { } //And see if there's a car back flyweight1 = getOneFlyweight(); if (flyweight1 != null) return flyweight1; //I didn't wait to buy a new car return newFlyweight(); } /** * Go buy a new bike * @return */ private synchronized Flyweight newFlyweight(){ ConcreteFlyweight flyweight = new ConcreteFlyweight(this.flyweightSize); flyweightSize++; flyweights.add(flyweight); return flyweight; } /** * Looking for a car in the car store * @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 meta category * Simulated single car */ class ConcreteFlyweight implements Flyweight { private int id; UnsharableFlyweight unsharableFlyweight; //0 is idle and 1 is occupied private volatile int state = 0; public ConcreteFlyweight(int id) { this.id = id; } /** * ride a bike * @param unsharableFlyweight */ @Override public synchronized void operate(UnsharableFlyweight unsharableFlyweight) { System.out.print("Current bicycle id:"+id+" "); unsharableFlyweight.operate(); } /** * occupy * * @return true:Occupation succeeded, 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; } } /** * Meta class interface * Simulated vehicles */ interface Flyweight { void operate(UnsharableFlyweight unsharableFlyweight); void release(); boolean occupy(); } /** * Specific non shared category * 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+"ride a bike"); } } /** * Non shared metaclass interface */ interface UnsharableFlyweight { void operate(); }
Here are nearly 200 lines of code, with a lot of comments. There is no credit or pain. I hope you can praise me for my hard work 👍.
summary
The focus of meta sharing mode is to share and reuse objects, store fine-grained objects, and apply them directly next time. There is no need to create them, avoiding the overhead of creating a large number of similar objects, so as to improve the performance of the system. Many pool technologies are based on the meta sharing mode, but the meta sharing mode can not be applied anywhere. It can only be used when there are a large number of objects of each type and the system does not depend on the state of these objects.
The sharing mode is very similar to the single example mode. I once doubted whether the sharing mode should be included in the creation mode. Now after learning, I find my suspicion is wrong. The meta pattern should be a structural pattern. It manages a group of objects. This group of objects is combined with the management class and focuses on the structure of objects. The singleton mode focuses on whether the object of this class is single and ensures that each class has only one object. The meta sharing mode is to save memory and improve performance. It does not guarantee that each class has only one object. Once the object is not enough, it will create a new object.