Java Design Patterns Series XIV (Hedonic Patterns)

Preface

Autumn rain, weekend afternoon, residential pavilion.

Uncle Li: Here you are. "

Me: "I'm here. "

Uncle Li: I know you will come! "

Me: "Of course I will come. Of course you know. How else would you let me go a day ago?"

I looked back at him again. It took me a long time to slow down and say, "Now the day is over.

Uncle Li: "A whole day. "

Me: "It's been a long day. "

Uncle Li: What a short day. "

Me: "Although I know I'm going to die today, I'm not the kind of person who waits to die. "

Uncle Li: "Now whether you have finished your work or not, your wish has been fulfilled. "

Autumn rain is still continuous, and there are few pedestrians.

Uncle Li: "Come on! "

Me: "A day ago, I was defeated by your men. "

Uncle Li said lightly: "Maybe you shouldn't have lost, but unfortunately your people are too young, but old chess skills. "

Me: "You lend me a day to do what I want to do. Now that the day is over, I... "

Uncle Li said, "You are here to die. "

Me: "Yes, I'm here to die. "

Me: "Now that I'm here, I'm bound to die. "

Uncle Li said, "You don't want to live another day?"

Suddenly, I looked up and laughed, and said, "If my husband was born, if he can't win all over the community grandfather in chess, the square dancing wave over the square grandmother, happy revenge, even if he lives another hundred years, it's better to live than die."

Uncle Li interrupted me and said coldly, "You're not a talkative person. I'm not here to talk to you. You just want to die quickly?"

Me: "Yes. "

Uncle Li exhaled, closed his eyes and stared, saying, "Please! Please go ahead. Today is still your first step. "

Above is the story of me and Uncle Li of the district. Since I can also appear here to write the public number, you should know the end of the story. Yes, I won that set. The next goal is Uncle Zhang of the district. Hey hey! Many friends should also have played Gobang or go, hundreds of pieces, divided into black and white, one move, after a short dozen rounds to surrender; the flag and drum equals you come and go, attack and defense in an orderly manner, hundreds of rounds are not winning or losing, full of black and white errors.

Well, back to the point, imagine if we want to use the program to design weiqi games, 181 sunspots and 180 whites, then do we have to go to a new chess object every time we play a piece? Java is an object-oriented language. We all know that if there are many new objects in memory, when the number of objects is too large and the recovery is not timely, it will lead to high running costs and performance degradation. So how can we solve this kind of problem? Next, we will explain the focus of this article, the Java design pattern - the hedonic pattern.

 

What is the hedonic model

To facilitate understanding, let's first look at the two states of the hedonic model:

  • Intrinsic State: The state that is stored within the hedger object and does not change with the environment, so the internal state can be shared.

  • Extrinsic State: A state that changes with the environment and cannot be shared. The external state of the hedgehog object must be saved by the client, and after the hedgehog object is created, it is passed into the inside of the hedgehog object when it needs to be used. One external state is independent of another.

The hedonic mode divides the state of an object into internal state and external state, in which the two are independent and share the same internal state. By setting different external states, the characteristics of an object can be changed, so that an object has different characteristics, but the internal state is always shared and can not be changed. That is to say, changing the external state will not cause the internal state to change.

You can imagine Go as a hedonic mode. Their size, shape and color are the internal state and the position of the chess pieces are the external state. So in the design, only two objects of black and white chess pieces are needed. Black chess shares the internal state of black, white chess shares the internal state of white, and the position of each chess piece on the chessboard is him. Their external state, the position of 361 intersections on the Go board, and the color (internal state) of the chess pieces will not be changed for each position (external state). Does that make sense?

The hedonic mode is usually used in conjunction with the factory mode in order to create a hedonic factory responsible for maintaining the Flyweight Pool, where the hedonic objects with the same internal state are stored. In the ever-changing daily business, there are very few internal states that can be shared, so the hedger objects are generally designed as smaller objects, including very few internal states, and these objects also become fine-grained objects.

Now let's look at the English definition of the hedonic model:

Flyweight Pattern: Use sharing to support large numbers of fine-grained objects efficiently.

Sharing technology is used to effectively support the reuse of a large number of fine-grained objects. Flyweight, I don't know why it's translated into heirloom in China. I can't find any information. It's probably translated according to the function and characteristics of this model. If you have any friends who know it, please leave a message at the end of the article to let me know. Thank you!

Look again at the domestic explanation of the hedonic model:

Flyweight Pattern: The use of sharing technology effectively supports the reuse of a large number of fine-grained objects. The system only uses a small number of objects, and these objects are very similar, state changes are very small, can achieve multiple reuse of objects. Since the hedonic pattern requires that the objects that can be shared must be fine-grained objects, it is also called lightweight pattern, and it is an object structural pattern.

In short: the purpose of the hedonic model is to reduce the number of objects and save memory by sharing the invariant parts.

 

Four roles of the hedonic model

  • Flyweight: Interfaces or abstract classes that declare common methods that provide the internal state of an object to the outside world and set the external state.

  • ConcreteFlyweight: Implements an abstract enjoyment class whose instance is called an enjoyment object. Must be shareable and need to encapsulate the internal state of the enjoyment object.

  • Unshared ConcreteFlyweight (non-shared concrete hedger class): Non-shared hedger implementation objects, not all hedger objects can be shared, non-shared hedger objects are usually combinations of hedger objects.

  • Flyweight Factory (Hedgehog Factory Class): Hedgehog Factory is mainly used to create and manage shared hedgehog objects, and to provide access to the shared hedgehog interface. It aims at abstract hedger class programming, and stores all kinds of specific hedger objects in a hedger pool. Generally, the hedger pool is designed as a set of "key-value pairs" (or other types of sets), which can be designed in combination with the factory pattern. When a user requests a specific hedger object, the hedger factory Provide an instance that has been created in the enjoyment pool or create a new instance if it does not exist, return the newly created instance and store it in the enjoyment pool.

 

UML diagrams of hedonic patterns

 

Code instance

I don't need the example of playing chess with Uncle Li, so as not to leave a trauma on his elder (young) mind. There are also many versions of chess pieces on the Internet. You can see them for yourself if you are interested. Let's take the King's Glory Game as an example. We know that in a match, every few minutes, there will be a wave of small soldiers and super soldiers. Small soldiers are the same length. Super soldiers are the same. If the King's team designs small soldiers when they come out, every small soldier will be a new small soldier object, then millions or even more people will be online corner at the same time. In the game, the server pressure simply can not withstand, but also can a good, smooth, happy score, pupils have been doing their homework well after school.

So how to design it? We can take the signs, assemblies and arms of the small soldiers as the internal state, and then take the direction of their attack on the map as the external state, so that no matter from which direction the small soldiers attack (how the external state changes), they will not change the signs and arms of the small soldiers (the internal state), so that when we develop, every soldier will be in the same position. The seed only needs one hedonic object. Look at the code:

1. Writing Abstract enjoyment classes


package com.weiya.mazhichu.designpatterns.flyweight;

/**
 * <p class="detail">
 * Function: Abstract enjoyment class
 * </p>
 *
 * @author Moore
 * @ClassName Soldier flyweight.
 * @Version V1.0.
 * @date 2019.09.03 21:06:52
 */
public interface SoldierFlyweight {
    /**
     * <p class="detail">
     * Function: enemy attack method
     * </p>
     *
     * @param direction :
     * @author Moore
     * @date 2019.09.03 21:06:52
     */
    public void attack(String direction);
}




2. Writing Specific Enjoyment Categories

package com.weiya.mazhichu.designpatterns.flyweight;

/**
 * <p class="detail">
 * Function: Specific Enjoyment Category
 * </p>
 *
 * @author Moore
 * @ClassName Concrete solider flyweight.
 * @Version V1.0.
 * @date 2019.09.04 09:45:41
 */
public class ConcreteSoliderFlyweight implements SoldierFlyweight {

    // Internal status
    private String soliderType;

    public ConcreteSoliderFlyweight(String soliderType) {
        this.soliderType = soliderType;
    }

    @Override
    public void attack(String direction) {
        if("normal".equals(soliderType)){
            System.out.println("Ordinary soldiers join the battlefield");
        }
        if("super".equals(soliderType)){
            System.out.println("Super Soldiers Join the Battlefield");
        }
        System.out.println("Direction of attack:"+direction);
    }
}

3. Writing Heyyuan Factory

package com.weiya.mazhichu.designpatterns.flyweight;

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

/**
 * <p class="detail">
 * Function: Hengyuan Factory
 * </p>
 *
 * @author Moore
 * @ClassName Soldier fly weight factory.
 * @Version V1.0.
 * @date 2019.09.03 21:06:58
 */
public class SoldierFlyWeightFactory {

    //Factory example
    private static SoldierFlyWeightFactory INSTANCE;
    // Hengyuanchi
    private static Map<String,SoldierFlyweight> soldierMap = new HashMap<String,SoldierFlyweight>();

    private SoldierFlyWeightFactory(){
        SoldierFlyweight normalSoldier = new ConcreteSoliderFlyweight("normal");
        soldierMap.put("normal",normalSoldier);
        SoldierFlyweight superSolider = new ConcreteSoliderFlyweight("super");
        soldierMap.put("super",superSolider);
    }

    /**
     * <p class="detail">
     * Function: Get factory instances
     * </p>
     *
     * @return soldier fly weight factory
     * @author Moore
     * @date 2019.09.03 21:07:02
     */
    public static SoldierFlyWeightFactory getInstance(){
        if(INSTANCE == null){
            INSTANCE = new SoldierFlyWeightFactory();
            return INSTANCE;
        }
        return INSTANCE;
    }

    /**
     * <p class="detail">
     * Function: Get the hedger object
     * </p>
     *
     * @param soliderType :
     * @return soldier flyweight
     * @author Moore
     * @date 2019.09.03 21:07:02
     */
    public SoldierFlyweight getSolider(String soliderType){
        return soldierMap.get(soliderType);
    }

    /**
     * <p class="detail">
     * Function: Get the number of Hedonic Pool objects
     * </p>
     *
     * @return int
     * @author Moore
     * @date 2019.09.03 21:07:02
     */
    public int getSoliderSize(){
        return soldierMap.size();
    }

}

4. Client Testing

package com.weiya.mazhichu.designpatterns.flyweight;

/**
 * <p class="detail">
 * Functions:
 * </p>
 *
 * @author Moore
 * @ClassName Honour of kings test.
 * @Version V1.0.
 * @date 2019.09.03 21:06:44
 */
public class HonourOfKingsTest {
    public static void main(String[] args) {

        System.out.println("The enemy has five seconds to go to the battlefield!");

        SoldierFlyWeightFactory factory = SoldierFlyWeightFactory.getInstance();

        SoldierFlyweight soldier1 = factory.getSolider("normal");
        SoldierFlyweight soldier2 = factory.getSolider("normal");
        SoldierFlyweight soldier3 = factory.getSolider("normal");

        soldier1.attack("Go on the road");
        soldier2.attack("Middle road");
        soldier3.attack("Next road");

        System.out.println(soldier1 == soldier2);
        System.out.println(soldier2 == soldier3);

        System.out.println("--------------------------");
        System.out.println("The dominant has been defeated!");

        SoldierFlyweight soldier4 = factory.getSolider("super");
        SoldierFlyweight soldier5 = factory.getSolider("super");
        SoldierFlyweight soldier6 = factory.getSolider("super");

        soldier4.attack("Go on the road");
        soldier5.attack("Middle road");
        soldier6.attack("Next road");

        System.out.println("Remaining blood of a magistrate, killed by super soldiers...");
        System.out.println(soldier4 == soldier5);
        System.out.println(soldier5 == soldier6);

        System.out.println("--------------------------");
        System.out.println("The case generates objects altogether:" + factory.getSoliderSize() + "individual");

    }
}

View the results of the operation:

We can see that we have sent six small soldiers, three ordinary soldiers and three super soldiers, but there are only two objects in Hengyuan Pool (one ordinary soldier and one super soldier). That is to say, no matter how many ordinary soldiers or super soldiers are sent, no matter which way they are going to attack, they will not affect the internal situation of the soldiers. State, so that the object of the whole system is greatly reduced, reducing memory consumption, no card will not affect the game experience, primary school students can happily come out of the pit, but to focus on learning!

 

Enjoyment Mode Extension

In the above example, we mainly talk about the specific object of share, that is, all the object of share must be shared. But among the four roles of the hedonic model, there is also a non-shared hedonic implementation object. What does that mean? As the name implies, the hedonic object does not necessarily need to be shared, but it is usually used as a composite object of the hedonic object. From this point of view, we divide the objects of enjoyment into:

  • Simple hedonic model: In simple hedonic model, all hedonic objects can be shared, that is, all subclasses of abstract hedonic classes can be shared, and there is no specific non-shared hedonic class.

  • Compound hedging mode: Some simple hedging elements can be combined using combination mode to form composite hedging objects. Such composite hedging objects themselves can not be shared, but they can be decomposed into simple hedging objects, while the latter can be shared. (Composite hedger objects implement Abstract hedger classes, whose instance is a non-shared hedger implementation object)

In the compound hedger model, each simple hedger object that composes the compound hedger object has its own internal state, and the external state of each simple hedger object is the same as the external state of the compound hedger object. Therefore, the compound hedger mode can set the same external state for multiple simple hedger objects, which is also the application scenario of the compound hedger mode.

I will not dwell on the simple hedonic model any more. Look at the above chess pieces or pesticide examples. The following is mainly about the combination hedonic model and why it is not shared. Let's look at the code:

1. Writing Compound Enjoyment Role Classes

package com.weiya.mazhichu.designpatterns.flyweight;

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

/**
 * <p class="detail">
 * Function: Compound hedger role class (non-shared hedger implementation object)
 * </p>
 *
 * @author Moore
 * @ClassName Concrete composite solider flyweight.
 * @Version V1.0.
 * @date 2019.09.04 10:56:11
 */
public class ConcreteCompositeSoliderFlyweight implements SoldierFlyweight {

    private static Map<String,SoldierFlyweight> soldierMap = new HashMap<String,SoldierFlyweight>();


    /**
     * <p class="detail">
     * Function: Increase the Pure Enjoyment Object
     * </p>
     *
     * @param soliderType :
     * @param flyweight   :
     * @author Moore
     * @date 2019.09.04 10:56:11
     */
    public void add(String soliderType,SoldierFlyweight flyweight){
        soldierMap.put(soliderType,flyweight);
    }

    /**
     * <p class="detail">
     * Function: FlWeights are a collection of simple hedger objects with the same external state extrinsic State.
     *     The attack method of a simple hedger object is called in a loop
     * </p>
     *
     * @param direction :
     * @author Moore
     * @date 2019.09.03 21:06:52
     */
    @Override
    public void attack(String direction) {
        SoldierFlyweight flyweight = null;
        for(String str : soldierMap.keySet()){
            flyweight = soldierMap.get(str);
            flyweight.attack(direction);
        }
    }

    /**
     * Remove the simple hedger object.
     * @param soliderType
     */
    private void remove(String soliderType) {
        soldierMap.remove(soliderType);
    }
}

2. Modified Heyuan Factory Role Class

package com.weiya.mazhichu.designpatterns.flyweight;

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

/**
 * <p class="detail">
 * Function: Hengyuan Factory
 * </p>
 *
 * @author Moore
 * @ClassName Soldier fly weight factory.
 * @Version V1.0.
 * @date 2019.09.03 21:06:58
 */
public class SoldierFlyWeightFactory {

    //Factory example
    private static SoldierFlyWeightFactory INSTANCE;
    // Hengyuanchi
    private static Map<String,SoldierFlyweight> soldierMap = new HashMap<String,SoldierFlyweight>();

    private SoldierFlyWeightFactory(){
        SoldierFlyweight normalSoldier = new ConcreteSoliderFlyweight("normal");
        soldierMap.put("normal",normalSoldier);
        SoldierFlyweight superSolider = new ConcreteSoliderFlyweight("super");
        soldierMap.put("super",superSolider);
    }

    /**
     * <p class="detail">
     * Function: Get factory instances
     * </p>
     *
     * @return soldier fly weight factory
     * @author Moore
     * @date 2019.09.03 21:07:02
     */
    public static SoldierFlyWeightFactory getInstance(){
        if(INSTANCE == null){
            INSTANCE = new SoldierFlyWeightFactory();
            return INSTANCE;
        }
        return INSTANCE;
    }

    /**
     * <p class="detail">
     * Function: Get the hedonic object (simple hedonic factory method)
     * </p>
     *
     * @param soliderType :
     * @return soldier flyweight
     * @author Moore
     * @date 2019.09.03 21:07:02
     */
    public SoldierFlyweight getSolider(String soliderType){
        return soldierMap.get(soliderType);
    }


    /**
     * <p class="detail">
     * Function: Compound Hedonic Factory Method
     * </p>
     *
     * @param compositeSoliderTypes :
     * @return soldier flyweight
     * @author Moore
     * @date 2019.09.04 11:06:24
     */
    public SoldierFlyweight getCompositeSolider(List<String> compositeSoliderTypes){
        ConcreteCompositeSoliderFlyweight compositeFlyweight = new ConcreteCompositeSoliderFlyweight();
        for(String soliderType : compositeSoliderTypes){
            compositeFlyweight.add(soliderType,this.getSolider(soliderType));
        }
        return compositeFlyweight;
    }

    /**
     * <p class="detail">
     * Function: Get the number of Hedonic Pool objects
     * </p>
     *
     * @return int
     * @author Moore
     * @date 2019.09.03 21:07:02
     */
    public int getSoliderSize(){
        return soldierMap.size();
    }
}

3. Writing Test Classes

package com.weiya.mazhichu.designpatterns.flyweight;

import java.util.ArrayList;
import java.util.List;

/**
 * <p class="detail">
 * Function: Testing pure and compound hedonic modes
 * </p>
 *
 * @author Moore
 * @ClassName Flyweight test.
 * @Version V1.0.
 * @date 2019.09.04 11:08:51
 */
public class FlyweightTest {
    public static void main(String[] args) {

        SoldierFlyWeightFactory factory = SoldierFlyWeightFactory.getInstance();

        String soliderType = "normal";
        SoldierFlyweight soldierFlyweight1 = factory.getSolider(soliderType);
        SoldierFlyweight soldierFlyweight2 = factory.getSolider(soliderType);
        soldierFlyweight1.attack("Go on the road");
        soldierFlyweight2.attack("Middle road");


        System.out.println("---------------------------------");

        List<String> compositeSoliderType = new ArrayList<String>();
        compositeSoliderType.add("normal");
        compositeSoliderType.add("super");
        compositeSoliderType.add("normal");
        compositeSoliderType.add("super");
        compositeSoliderType.add("normal");


        SoldierFlyweight compositeSoliderFlyeweight1 = factory.getSolider(compositeSoliderType);
        SoldierFlyweight compositeSoliderFlyeweight2 = factory.getSolider(compositeSoliderType);
        compositeSoliderFlyeweight1.attack("Go on the road");
        compositeSoliderFlyeweight2.attack("Middle road");

        System.out.println("---------------------------------");
        System.out.println("Does the simple hedonic mode share objects?" + (soldierFlyweight1 == soldierFlyweight2));
        System.out.println("Does the compound hedge mode share objects?" + (compositeSoliderFlyeweight1 == compositeSoliderFlyeweight2));

    }
}

View the results of the operation:

Combined with the results of the operation, and then look at this paragraph word by word, you should be able to understand.

In the compound hedger model, each simple hedger object that composes the compound hedger object has its own internal state, and the external state of each simple hedger object is the same as the external state of the compound hedger object. Therefore, the compound hedger mode can set the same external state for multiple simple hedger objects, which is also the application scenario of the compound hedger mode.

 

Compound hedge schema UML diagram

 

Summary of Heyuan Model

Use scenarios

  • The system has a large number of similar or identical objects. Due to the large use of such objects, a large amount of memory is consumed.

  • Scenarios where buffer pools are required (hedonic pools, i.e., when hedonic objects need to be used multiple times).

  • Most of the state of an object can be externalized, and these external states can be passed into the object.

Advantage

  • It greatly reduces the creation of objects, reduces the memory of the system, and improves the efficiency.

  • The external state of the enjoyment mode is relatively independent and does not affect its internal state, so that the enjoyment object can be shared in different environments.

shortcoming

  • External state and internal state need to be separated to improve the complexity of the system.

  • Reading the external state of the enjoyment mode makes the run time slightly longer.

Okay, let's talk about the Hengyuan model. It's a little longer. You may need to read it several times more slowly to understand it. Thank you for seeing this. I hope it will help you a little. I'm satisfied.

 

I can't guarantee that my articles are correct, but I can guarantee that I spent my time and effort writing them. All the code examples are original. All the understandings are only my personal understandings and can't represent the official authority. So please read with critical eyes and selective approval. Thank you.

If you think this article is useful, please recommend to the people around you or colleagues concerned about the "code beginning" public number, let's move forward together, thank you!

If you find problems in the article or bug s in the code, you are welcome to leave a message, please feel free to criticize and correct, thank you!

In order to thank you for your attention and love, at the beginning of the code for the small partners looking for work quietly sent a batch of dry goods, the background sent "interview" keywords, you can get a random interview information, I wish all small partners step by step, the future is bright!

Tags: Programming Java

Posted on Wed, 04 Sep 2019 21:12:33 -0700 by Exdaix