Design Mode~Hedonic Mode

Keywords: Java JDK

concept

Flyweight Pattern is a shared way to reuse a large number of fine-grained objects to reduce memory usage (to avoid creating and destroying objects in large amounts repeatedly).

The Flyweight in the name is one of the weight levels in a fight match. It is known in Chinese as the fly weight or the next lightest weight.Porting this word into software engineering is also used to represent very small objects, that is, fine-grained objects.Thus, the feature of the share mode is not only sharing, but also the fine-grained sharing.

Internal state, external state, enjoyment pool

The same content that can be shared in the enjoyment class is called the internal state, and the specific content that needs to be set by the external environment is called the external state. They are independent, decoupled, and combined to form the enjoyment class.Different but related (such as the same class) enjoyment objects are aggregated to form an enjoyment pool that is maintained using an enjoyment factory.
This calls the enjoyment factory (in its maintained enjoyment pool) to get the desired enjoyment object and configure its external state for use as required.

Because internal and external states are distinguished, different external states can be set to make the same object have some different characteristics, while the same internal state can be shared.Therefore, the essence of the hedonic mode is to decouple complete objects into finer granularity, decouple and unchange them, and share them unchanged, so as to reduce the number of objects and save memory.

The hedonic model refers to the sharing of the single-case model and the unified supply of the factory model, which is characterized by the reuse of fine-grained objects.
The difference from the singleton pattern is that fine-grained reuse does not reuse complete objects.

Role & UML

Abstract enjoyment class
 Specific Enjoyment Class
 FlyweightFactory
 Client

Demo: Editor Picture Reuse - Java

Requirements:
Enjoyment mode is used extensively in editor software, for example, when the same picture appears multiple times in a document, you only need to create a picture object, which can be repeated multiple times in different places by setting where the picture appears in the application.

UML:

Code structure:

./
├── Client.java
├── ImageNodeFactory.java
├── flyweight
│   ├── BirdImage.java
│   ├── ImageNode.java
│   ├── TreeImage.java
│   ├── bird.jpeg
│   └── tree.jpg
└── result.pdf

Here, PDF editing uses the itextpdf package.Pom.xmlConfiguration in

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13</version>
</dependency>

ImageNode <Interface>: Abstract enjoyment class

package homework.Flyweight.flyweight;

import com.itextpdf.text.BadElementException;

import com.itextpdf.text.Image;
import java.io.IOException;

public interface ImageNode {


//    Returns a picture (internal state) object wrapped with coordinates (external state < parameters)
    public Image getImageInPdf(int x, int y) throws IOException, BadElementException;
}

BirdImage <Class>: specific enjoyment class

package homework.Flyweight.flyweight;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Image;

import javax.imageio.ImageIO;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

public class BirdImage implements ImageNode {

//    The internal state of the enjoyment maintenance (pictures, sharing)
    private byte[] image;

//    Load Internal Status (Picture)
    public BirdImage() throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        ImageIO.write(
                ImageIO.read(new File("src/main/java/homework/Flyweight/flyweight/bird.jpeg")),
                "jpeg",
                baos);

        this.image = baos.toByteArray();
    }

    @Override
    public Image getImageInPdf(int x, int y) throws IOException, BadElementException {
        Image imageInPdf = Image.getInstance(this.image);

//        Internal Status (Picture Object) + External Status (Picture Location)
        imageInPdf.scaleAbsolute(30, 30);
        imageInPdf.setAbsolutePosition(x, y);

//        Print the address of the picture in memory
        System.out.println(this.image);
        return imageInPdf;
    }
}

TreeImage <Class>: specific enjoyment class

package homework.Flyweight.flyweight;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Image;

import javax.imageio.ImageIO;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

public class TreeImage implements ImageNode {

//    The internal state of the enjoyment maintenance (pictures, sharing)
    private byte[] image;

//    Load Internal Status (Picture)
    public TreeImage() throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        ImageIO.write(
                ImageIO.read(new File("src/main/java/homework/Flyweight/flyweight/tree.jpg")),
                "jpg",
                baos);

        this.image = baos.toByteArray();
    }

    @Override
    public Image getImageInPdf(int x, int y) throws IOException, BadElementException {
        Image imageInPdf = Image.getInstance(image);

//        Internal Status (Picture Object) + External Status (Picture Location)
        imageInPdf.scaleAbsolute(30, 30);
        imageInPdf.setAbsolutePosition(x, y);

//        Print the address of the picture in memory
        System.out.println(this.image);
        return imageInPdf;
    }
}

ImageNodeFactory <Class>: Heyuan Factory

package homework.Flyweight;

import homework.Flyweight.flyweight.BirdImage;
import homework.Flyweight.flyweight.ImageNode;
import homework.Flyweight.flyweight.TreeImage;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ImageNodeFactory {

//    Heyuan Pool maintained by Heyuan Factory
    private static Map<String, ImageNode> imagePool = new ConcurrentHashMap<>();

//    Get your share
    public static ImageNode getImageNode(String type) throws IOException {
        if(!imagePool.containsKey(type)) {
            switch (type) {
                case "bird":
                    imagePool.put(type, new BirdImage());
                    break;
                case "tree":
                    imagePool.put(type, new TreeImage());
                    break;
            }
        }

        return imagePool.get(type);
    }

}

Client <Class>: Client

package homework.Flyweight;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfWriter;
import homework.Flyweight.flyweight.ImageNode;

import java.io.*;

public class Client {

    public static void main(String[] args) throws IOException, DocumentException {

//        1. Initialize PDF
        Rectangle rectangle = new Rectangle(PageSize.A4);       // Set PDF paper rectangle with A4 size
        rectangle.setBackgroundColor(BaseColor.WHITE);          // Set Background Color
        // Create a document object with initialization size and margins
        Document document = new Document(rectangle, 10, 10, 10, 10);     // Top, bottom, left, right page spacing

        String pdfPath = "src/main/java/homework/Flyweight/result.pdf";   // Output location of PDF
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdfPath));


        document.open();    // Open Document Object

//        2. Insert pictures in PDF
        for(int i=0; i<10; i++){
            ImageNode imageNode = ImageNodeFactory.getImageNode("tree");
//            Picture coordinates (external state) are maintained by the client
            document.add(imageNode.getImageInPdf(10*i,100*i));
            
            System.out.println("Object ImageNode: "+imageNode);

        }

        document.close();   // close document
    }
}

Console Printing:

[B@16b4a017
Object ImageNode: homework.Flyweight.flyweight.TreeImage@5ecddf8f
[B@16b4a017
Object ImageNode: homework.Flyweight.flyweight.TreeImage@5ecddf8f
[B@16b4a017
Object ImageNode: homework.Flyweight.flyweight.TreeImage@5ecddf8f
[B@16b4a017
Object ImageNode: homework.Flyweight.flyweight.TreeImage@5ecddf8f
[B@16b4a017
Object ImageNode: homework.Flyweight.flyweight.TreeImage@5ecddf8f
[B@16b4a017
Object ImageNode: homework.Flyweight.flyweight.TreeImage@5ecddf8f
[B@16b4a017
Object ImageNode: homework.Flyweight.flyweight.TreeImage@5ecddf8f
[B@16b4a017
Object ImageNode: homework.Flyweight.flyweight.TreeImage@5ecddf8f
[B@16b4a017
Object ImageNode: homework.Flyweight.flyweight.TreeImage@5ecddf8f
[B@16b4a017
Object ImageNode: homework.Flyweight.flyweight.TreeImage@5ecddf8f

Process finished with exit code 0

Generated PDF:

Reference

  1. https://www.jianshu.com/p/f9997c0c2a55
  2. Enjoyment mode - Lianliankan picture sharing https://blog.csdn.net/ABAP_Brave/article/details/78528416
  3. Viewing Design Mode with JDK Source --- Enjoyment Mode

Posted by idevlin on Sat, 23 May 2020 09:56:32 -0700