"Design Pattern" flyweight mode

1. What is the flyweight model?

Flyweight mode effectively supports fine-grained object reuse with small state changes through sharing technology. When there are multiple identical objects in the system, only one copy is shared, and there is no need to instantiate an object for each one, which greatly reduces The number of objects in the system. For example, in a text system, each letter defines an object. Then there are 52 uppercase and lowercase letters in total, so 52 objects must be defined. If there is a 1M text, there are so many letters. If each letter defines an object, the memory will be exhausted. So if each letter shares an object, then resources will be greatly saved.

Before understanding the flyweight mode, we must first understand two concepts: internal state and external state.

  • Internal state: The shared part within the flyweight object that does not change with changes in the external environment.
  • External state: changes as the environment changes, and the state that cannot be shared is the external state.

Since the flyweight pattern distinguishes between internal state and external state, we can set different external states so that the same object can have some different characteristics, while the internal state is set to the same part. In our programming process, we may need a large number of fine-grained objects to represent objects. If these objects are the same except for a few different parameters, then we can use the flyweight pattern to greatly reduce the number of steps in the application. Object. How to use flyweight mode? Here we only need to move a small number of their different parts as parameters to the outside of the class instance, and then pass them over when the method is called. This also illustrates one point: the internal state is stored inside the flyweight object, while the external state should be considered by the client.

2. UML structure diagram

  • (1) Flyweight: abstract flyweight class, the superclass or interface of all concrete flyweight classes. Through this interface, Flyweight can accept and act on external topics;
  • (2) ConcreteFlyweight: Concrete flyweight class. Specify the internal state and add storage space for the internal state.
  • (3) UnsharedConcreteFlyweight: Unshared concrete flyweight class. Indicates those Flyweight subclasses that do not need to be shared.
  • (4) FlyweightFactory: Flyweight factory class, used to create and manage Flyweight objects. It is mainly used to ensure reasonable sharing of Flyweight.

The core of the flyweight model is the flyweight factory class. The flyweight factory class maintains an object storage pool. When the client needs an object, it first obtains it from the flyweight pool. If there is an object instance in the flyweight pool, it will be returned directly. If If it does not exist in the flyweight pool, a new flyweight object instance is created and returned to the user, and the new object is saved in the flyweight pool. This has the meaning of a singleton.

Factory classes usually use collection types to save objects, such as HashMap, Hashtable, Vector, etc. In Java, database connection pools, thread pools, etc. are all applications that use the Flyweight mode.

public class FlyweightFactory{
    private HashMap flyweights = new HashMap();
    
    public Flyweight getFlyweight(String key){
        if(flyweights.containsKey(key)){
            return (Flyweight)flyweights.get(key);
        }
        else{
            Flyweight fw = new ConcreteFlyweight();
            flyweights.put(key,fw);
            return fw;
        }
    }
}

3. Code implementation

Scenario: If we have a drawing application through which we can draw graphics of various shapes and colors, then the shape and color here are internal states. Through the flyweight mode we can realize the sharing of this attribute . as follows:

First is the shape class: Shape.java. It is an abstract class with only one abstract method for drawing graphics.

public abstract class Shape {
    public abstract void draw();
}

Then there is the concrete class for drawing circles. Circle.java:

public class Circle extends Shape{
    private String color;
    public Circle(String color){
        this.color = color;
    }
 
    public void draw() {
        System.out.println("画了一个" + color +"的圆形");
    }
}

Then there is the flyweight factory class. FlyweightFactory:

//核心类
public class FlyweightFactory{
    static Map<String, Shape> shapes = new HashMap<String, Shape>();
    
    public static Shape getShape(String key){
        Shape shape = shapes.get(key);
        //如果shape==null,表示不存在,则新建,并且保持到共享池中
        if(shape == null){
            shape = new Circle(key);
            shapes.put(key, shape);
        }
        return shape;
    }
    
    public static int getSum(){
        return shapes.size();
    }
}

A HashMap is defined here to store each object. When the user needs an object, it first obtains it from the flyweight pool. If it does not exist in the flyweight pool, a new flyweight object is created and returned to the user, and is stored in the flyweight pool. Save the new object in .

Finally, the client program: Client.java:

public class Client {
    public static void main(String[] args) {
        Shape shape1 = FlyweightFactory.getShape("红色");
        shape1.draw();
        
        Shape shape2 = FlyweightFactory.getShape("灰色");
        shape2.draw();
        
        Shape shape3 = FlyweightFactory.getShape("绿色");
        shape3.draw();
        
        Shape shape4 = FlyweightFactory.getShape("红色");
        shape4.draw();
        
        Shape shape5 = FlyweightFactory.getShape("灰色");
        shape5.draw();
        
        Shape shape6 = FlyweightFactory.getShape("灰色");
        shape6.draw();
        
        System.out.println("一共绘制了"+FlyweightFactory.getSum()+"中颜色的圆形");
    }
}

operation result:

In Java, the String type uses the flyweight pattern . The String object is a final type and cannot be changed once the object is created. Java's string constants are stored in the string constant pool, and the JVM will ensure that there is only one copy of a string constant in the constant pool. 

String a="abc", where "abc" is a string constant. Those familiar with Java should know the following example:

String a = "hello";
String b = "hello";
if(a == b)
 System.out.println("OK");
else
 System.out.println("Error");

The output is: OK. It can be seen that the if condition compares the addresses of two a and b, which can also be said to be the memory space.

4. Advantages and Disadvantages of Flyweight Model

4.1. Advantages of flyweight mode:

(1) Greatly reduce the number of objects in the system;

(2) Since the external state is used, the external state is relatively independent and will not affect the internal state, so the flyweight mode allows flyweight objects to be shared in different environments.

4.2. Disadvantages of flyweight mode:

(1) Since the flyweight pattern needs to distinguish between external state and internal state, the application becomes more complicated to a certain extent.

(2) In order to make the object shareable, the state of the flyweight object needs to be externalized, and reading the external state makes the running time longer.

4.3. Applicable scenarios:

(1) If there are a large number of identical or similar objects in the system, the large use of such objects will cause system memory consumption. You can use the flyweight mode to reduce the number of objects in the system.

(2) Most of the state of the object can be externalized, and these external states can be passed into the object.

Reference article:  Structural type of Java design pattern: flyweight pattern_Zhang Weipeng's blog-CSDN blog

Guess you like

Origin blog.csdn.net/m0_50370837/article/details/126305428