Design patterns to enjoy with frequently used Java libraries --Strategy patterns

GoF design patterns are also hidden in the Java libraries that you use most often. It's easy to overlook the busy daily work, but once in a while, let's take a closer look at the beautiful design, which can be said to be a kind of art.

This art

source file

Main.java


import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Main {

    public static void main(String[] args) {
        //Create an instance of GSON
        Gson gson = new GsonBuilder()
                .setFieldNamingStrategy(new MyFieldNamingStrategy())
                .create();

        //Convert Java objects to JSON strings
        String json = gson.toJson(new ExampleBean());

        //output
        System.out.println(json);
    }
}

MyFieldNamingStrategy.java


import com.google.gson.FieldNamingPolicy;
import com.google.gson.FieldNamingStrategy;
import java.lang.reflect.Field;

public class MyFieldNamingStrategy implements FieldNamingStrategy {

    @Override
    public String translateName(Field field) {
        //Of member variables"_"Get rid of
        String fieldName = FieldNamingPolicy.IDENTITY.translateName(field);
        if (fieldName.startsWith("_")) {
            fieldName = fieldName.substring(1);
        }
        return fieldName;
    }
}

ExampleBean.java


public class ExampleBean {
    //At the beginning of member variables"_"Is attached
    private String _firstField = "value";
    private String _secondField = "vaule";
}

Execution result

//At the beginning of a member variable"_"Is taken
{"firstField":"value","secondField":"vaule"}

This is a scene to convert a Java object to a JSON string using the Gson library. When you watch it again, you will be thrilled with the interface that seems to be both simple and customizable.

Points of appreciation

Gson is an open source library made by Google that converts Java objects <=> JSON to each other. I'm using this Gson library to convert the ʻExampleBean` class to JSON.

The ʻExampleBean` class was probably written by a C ++ or Objective-C programmer. Unusual in Java, member variables are prefixed with "\ _" (underscore). However, I don't want to add "\ _" to the JSON generated this time.

Gson is designed to set FieldNamingStrategy to GsonBuilder as the logic to determine the field name (JSON key name) when converting a Java object to JSON. In the "Template Method pattern" I wrote in the previous article, it was a mechanism to inherit the parent class in order to customize the function. This time, I set an instance of the class. There seems to be a design aesthetic in using inheritance as little as possible in customizing features. Let's explore together.

If you don't use the Strategy pattern

The code at the beginning uses the Strategy pattern, but first, let's think about what the design would look like without the Strategy pattern, as if you were the designer of the Gson library.

What I want to do is not to add "\ _" when converting a class that has "\ _" in the field name to JSON. It is assumed that there are many classes to be converted, and that the class cannot be refactored to change the field name.

Design with inheritance

Class inheritance is the first thing we talk about in object-oriented programming, so let's try designing with inheritance. Let's implement the logic that determines the field name by inheriting the Gson class [^ 1].

MyGson.java


public class MyGson extends Gson {
    @Override
    protected String translateFieldName(Field field) {
        //At the beginning of the field name"_"If is attached, the removed character string is returned.
        // "_"If there is no, return it as it is.
    }
}

Main.java


...
public class Main {

    public static void main(String[] args) {
        //Create an instance of GSON
        Gson gson = new MyGson();

        //Convert Java objects to JSON strings
        String json = gson.toJson(new ExampleBean());

        //output
        System.out.println(json);
    }
}

It's refreshing than I expected ... The MyGson class implements the logic to translate field names by overriding the parent class's translateFieldName method. The overridden method is called from the parent class Gson class when creating a JSON string. This method is the "Template Method pattern" I wrote in the previous article. It's simpler and easier to understand than you can imagine.

Problems with designing with inheritance

In this situation, you can't help thinking, "It's an overwhelming victory for the Template Method pattern. I didn't have a Strategy pattern."

However, field names are not the only things that Gson can customize. Looking at Gson's Javadoc, there are many other customizable points besides field names.

  1. setExclusionStrategy --Define classes and fields not included in JSON
  2. setLongSerializationPolicy --Defines whether the Long type is a number or a number
  3. setDateFormat --Define the format for converting Date type to string

Etc.

If you do all these customizations with parent class inheritance, you're in trouble. That is, the combination of features will explode.

For example, suppose you are using a class of Gson1 that overrides the function of 1 above, Gson2 that overrides the function of 2, and Gson3 that overrides the function of 3.

1 function 2 functions 3 features
Gson1 class
Gson2 class
Gson3 class

In this situation, when you need both new 1 and 2 features, you'll need a Gson12 class that overrides both methods. The source code is duplicated because the contents of the method are exactly the same as those described in Gson1 and Gson2 respectively.

1 function 2 functions 3 features
Gson1 class
Gson2 class
Gson3 class
Gson12 class

Furthermore, if you need the functions 1 and 3, you need the Gson13 class as well, and if you need the functions 1, 2 and 3, you need to create the Gson123 class.

1 function 2 functions 3 features
Gson1 class
Gson2 class
Gson3 class
Gson12 class
Gson13 class
Gson123 class
...

In this way, if you try to solve it by ** inheritance of the Gson class, the worst design is that you need as many classes as there are combinations of functions and the source code is duplicated **.

As another method using inheritance, it is possible to inherit the ʻExampleBean class that converts to JSON and implement each method such as translateFieldName` here. However, it still encounters the same problem as above, and it goes against the Gson specification philosophy of being able to convert POJOs (ordinary Java objects) to JSON in the first place.

When using the Strategy pattern

Now let's apply the Strategy pattern. For the source code and execution result, see [Opening](#this art) again.

The flow of this Strategy pattern is as follows.

  1. GsonBuilder sets MyFieldNamingStrategy to Gson
  2. MyFieldNamingStrategy # translateName is called when translating a field name in Gson # toJson

The point is that the process of converting field names is delegated to MyFieldNamingStrategy rather than directly in the Gson class. By doing this, ** the main class (Gson) and the conversion logic class (XXXStrategy) can be separated **. Separation makes it easy to replace or reuse logic in a sneak peek. beautiful!

The GoF definition of the Strategy pattern is "Define a family of algorithms, encapsulate each one, and make them interchangeable. The Strategy pattern allows the algorithm used by the client to be modified independently. [^ 2] ". The "algorithm family" here corresponds to functions such as converting field names (XXXStrategy class).

Expert comments on the Strategy pattern

Many experts have also commented on evaluating the Strategy pattern.

Hiroshi Yuki

In the Strategy pattern, the part that implements the algorithm can be exchanged in a sneak peek. The Strategy pattern is a pattern that makes it easy to switch algorithms (strategies, strategies, strategies) and solve the same problem in different ways.

["Introduction to Design Patterns Learned in Java Language"](https://www.amazon.co.jp/ Introduction to Design Patterns Learned in Java Language-Yuki-Hiroshi / dp / 4797327030 /)

lang_and_engine

When it comes to a somewhat complicated algorithm, a normal programmer will cut out and aggregate that part. It should also be compatible in case it is replaced by another algorithm.

From List of 23 GoF design patterns to utilize in Java

Finally

It's the real pleasure of programmers to be able to enjoy intellectual enjoyment by just looking at a few lines of code without having to go to the museum.

If you are an engineer who sympathizes with the artistry of the Strategy pattern, please contact the recruiting staff of our company (Qualysite Technologies Inc.). Contact Please!

Supplement (Gson Tips)

In the above example, the FieldNamingStrategy class was used to convert the field name in Gson, but you can also decide the name in JSON by just annotating the member variables of the class to be converted. This is convenient when there are few classes to be converted.

ExampleBean.java


public class ExampleBean {
    @SerializedName("firstField")
    private String _firstField = "value";

    @SerializedName("secondField")
    private String _secondField = "vaule";
}

Reference URL

Related article

Create an instance

-Design pattern to enjoy with Java library used frequently --Factory pattern -Design patterns to enjoy with frequently used Java libraries --Builder patterns -Design patterns to enjoy with frequently used Java libraries --Abstract Factory pattern

Simplify the interface

-Design patterns to enjoy with Java libraries that are often used --Facade patterns -Design pattern to enjoy with frequently used Java library --Adapter pattern

Leave it to another class

-Design patterns to enjoy with frequently used Java libraries --Template Method patterns --Design patterns to enjoy with frequently used Java libraries --Strategy patterns

[^ 1]: The Gson class is declared final and cannot actually be inherited. Assuming that you are the designer of Gson, you are in the process of considering what kind of design you should make. [^ 2]: ["Design pattern for reuse in object orientation"](https://www.amazon.co.jp/%E3%82%AA%E3%83%96%E3%82%B8 % E3% 82% A7% E3% 82% AF% E3% 83% 88% E6% 8C% 87% E5% 90% 91% E3% 81% AB% E3% 81% 8A% E3% 81% 91% E3 % 82% 8B% E5% 86% 8D% E5% 88% A9% E7% 94% A8% E3% 81% AE% E3% 81% 9F% E3% 82% 81% E3% 81% AE% E3% 83 % 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3% 83% B3-% E3% 82% AC% E3% 83% B3% E3% 83% 9E-% E3% 82% A8% E3% 83% AA% E3% 83% 83% E3% 82% AF / dp / 479731126 / ref = sr_1_1? Ie = UTF8 & qid = 1495503419 & sr = 8-1 & keywords =% E3% 82% AA% E3% 83% 96% E3% 82% B8% E3% 82% A7% E3% 82% AF% E3% 83% 88% E6% 8C% 87% E5% 90% 91% E3% 81% AB% E3% 81% 8A% E3% 81% 91% E3% 82% 8B% E5% 86% 8D% E5% 88% A9% E7% 94% A8% E3% 81% AE% E3% 81% 9F% E3% 82% 81% E3% 81% AE% E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% From 91% E3% 82% BF% E3% 83% BC% E3% 83% B3)

Recommended Posts

Design patterns to enjoy with frequently used Java libraries --Strategy patterns
Design patterns to enjoy with frequently used Java libraries --Builder patterns
Design patterns to enjoy with frequently used Java libraries --Adapter patterns
Design patterns to enjoy with frequently used Java libraries --Template Method patterns
Design patterns to enjoy with frequently used Java libraries --Facade pattern
Design patterns to enjoy with frequently used Java libraries --Abstract Factory pattern
Design patterns learned with Java & PHP (summary)
Strategy on how to monetize with Python Java
Docker. Set frequently used commands to alias "with explanation"
[Updated from time to time] Summary of design patterns in Java
Summary of Chapter 2 of Introduction to Design Patterns Learned in Java Language
Chapter 4 Summary of Introduction to Design Patterns Learned in Java Language
Summary of Chapter 3 of Introduction to Design Patterns Learned in Java Language