Structural design mode -- enjoy element mode FlyWeight

gossip

Today is the weekend. I wanted to be lazy. Let's think about a design pattern
It's not well written. Welcome to discuss it together~

Basic points

1. Usage scenario: memory is a scarce resource. If there are many identical or similar objects, we can save memory through meta sharing mode

2. Core
– support the reuse of a large number of fine-grained objects in a shared manner

– the key to sharing meta objects is to distinguish between internal and external states
Internal status: it can be shared and will not change with the environment
External status: it cannot be shared and will change with the environment

For example, go software
Each chess piece can be regarded as an object, and the color, shape and size can be called the internal state, because these can be shared
However, each chess piece is unique and cannot be shared, so it is an external state

3. Implementation of meta mode
– FlyweightFactory element sharing factory class: create and manage element sharing objects. Element sharing pools are generally designed as key value pairs (which can be understood as maps)
– FlyWeight Abstract meta object: usually an interface or abstract class, which is used to declare public methods. These methods can provide the internal state of the object to the outside world and set the external state. The chess pieces in the example can be regarded as this
– ConcreteFlyWeight specific meta class: put the internal state here and provide member variables for internal state storage
– UnsharedConcreteFlyWeight unshared meta class: put the external state here, and subclasses that cannot be shared can be designed as unshared meta classes

4. Advantages and disadvantages of sharing mode
Advantages: it greatly reduces the number of objects in memory, saves system resources, and the external state is relatively independent without affecting the internal state.
Disadvantages: the mode is complex, which complicates the program logic; In order to save memory, the internal state is shared and the external state is separated. However, it takes a long time to read the external state and sacrifice time for space.

Implementation code

We take the go system above as an example
First, we create a meta class and a specific meta class

/**
 * Shared meta class, that is, FlyWeight Abstract shared meta object
 */
public interface ChessFlyWeight {
    // Get chess piece color (get internal status)
    String getColor();

    // Set chess coordinates (set external state)
    void display(Coordinate coordinate);
}

/**
 * ConcreteFlyWeight Specific meta class: put the internal state here and provide member variables for storage
 */
class ChessConcreteFlyWeight implements ChessFlyWeight {
    // Provide member variables for internal state storage
    private String color;

    public ChessConcreteFlyWeight(String color) {
        this.color = color;
    }

    @Override
    public String getColor() {
        return color;
    }

    @Override
    public void display(Coordinate coordinate) {
        System.out.println("Chess piece color:" + color);
        System.out.println("Chess coordinates: x= " + coordinate.getX() + "y=" + coordinate.getY());
    }
}

Create a non shared metaclass and put the external state here

/**
 * External state related class, UnsharedConcreteFlyWeight unshared meta class
 */
public class Coordinate {
    // The coordinates of chess pieces are external states
    private int x,y;

    public Coordinate(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

Create a meta factory

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

/**
 * Xiangyuan factory
 */
public class ChessFlyWeightFactory {
    // Xiangyuan pool
    private static Map<String, ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>();

    // Get chess sub object according to color
    public static ChessFlyWeight getChess(String color) {
        // If there is a chess sub object that meets the current color requirements, it returns
        if (null != map.get(color)) {
            return map.get(color);
        } else {
            // If there is no matching object, create a new chess sub object, and then put it into the sharing pool. After returning
            ChessFlyWeight chess = new ChessConcreteFlyWeight(color);
            map.put(color, chess);
            return chess;
        }
    }
}

Simulation client

public class Client {
    public static void main(String[] args) {
        ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("black");
        ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("black");
        // When chess1 is created, there are no black chess pieces in the sharing pool, so one is created. When chess2 is obtained, there are black chess pieces, so you can directly get the object created before
        System.out.println(chess1);
        System.out.println(chess2);

        System.out.println("Add external status processing===========");
        chess1.display(new Coordinate(10, 10));
        chess2.display(new Coordinate(20, 20));
    }
}

The operation results are shown in the figure

If there is any mistake, please correct it

Tags: Java Design Pattern Back-end

Posted on Tue, 30 Nov 2021 16:22:24 -0500 by ZachMEdwards