Author: Xiao Fu Ge blog: Bugstack.cn – original series of special articles

Precipitation, share, grow, let yourself and others can gain something! 😄

One, foreword

Luan qī bā zāo, I have often suspected that this idiom is used to describe a programming monkey!

Whether or not to undertake what kind of demand, is surrounded by a few people write bad code, but they often have a test to the little sister chat (bug) instead, the junior partner to send products to eat (a written demand), have business change little sister accompany code (online), until the leadership think his work is very important, and beside you have to rub something to eat.

What else does the CRUD code want from me?

This kind of friend may write the code is very direct, ifelse a little bit more, content to temporarily support, thinking that it is ok. And this kind of business needs urgent and is to add, delete, change and check the content, really do not want to do design. And if someone mentions design well, it’s probably frowned upon not to over-design.

Patch patch like a plaster, each time more horrible!

It’s really quick to get the product requirements done for the first time, but the code on the Internet is not as good as in a traditional enterprise. In a traditional industry, a set of code may last ten years, but in high-speed iterations of the Internet your project will change dozens of times a year. If you start with the idea that you just need to complete the function, then the subsequent requirements will be difficult to undertake, and each time you look at pieces of code, you really don’t know how to start.

In the r & D process specifications under the implementation, to write a good program!

The launch of a project often has to go through business requirements, product design, R&D implementation, testing and verification, online deployment to the formal open volume, which is very important for RESEARCH and development is the process of r&d implementation, and can include; Architecture selection, functional design, design review, code implementation, code review, single test coverage check, documentation, test submission. So with some of the process specifications, it’s really hard to get code out there.

The process of developing code is not showy, just like building a house if you don’t follow the blueprint, you build a kitchen bathroom on the gable! This may sound ridiculous in a real world scenario, but there is always code like this in feature development.

So we also need some standard ideas of design patterns to build code structures and improve global control.

Second, development environment

  1. JDK 1.8
  2. Idea + Maven
  3. Involving engineering three, can be concerned byThe public,:Bugstack wormhole stackReply,Download the source codeGet (Open the get link and find the serial number 18)
engineering describe
itstack-demo-design-3-00 Scene simulation project, simulation of the selection of packages in the decoration process (luxurious, pastoral, simple)
itstack-demo-design-3-01 Using a lump of code to implement business requirements is also the use of ifelse
itstack-demo-design-3-02 Design patterns are optimized to adapt code to generate contrast for learning

Iii. Introduction of builder model

What the Builder pattern does is build a complex object by assembling simple objects step by step.

So where is this scenario?

For example, the initialization screen when you play King of Glory; There are three roads, trees, wild creatures, guard towers, etc., and even control clarity depending on your network situation. When you change the scene to a different mode selection, you will also build roads, trees, monsters, etc., but they will be placed and sized differently. This is where the Builder pattern is used to initialize game elements.

And the concrete content produced by different assembly based on the same material is the ultimate intention of the builder mode, namely; Separating a complex build from its representation allows the same build process to create different representations.

4. Case scenario simulation

Here we simulate the decoration company for the design of some package decoration service scene.

Many decoration companies will give their own package service, generally have; European luxury, light luxury pastoral, modern simplicity and so on, and the back of these packages is a combination of different goods. For example; Level 1 & level 2 ceiling, Dulux paint, Holy image floor, Marco Polo floor tiles and so on, according to the price of different packages to select different brand combinations, and finally according to the decoration area to give an overall offer.

Here we simulate the decoration company wants to launch some package decoration services, according to different prices to set the brand choice combination, in order to achieve the process of using the builder model.

1. Scene simulation engineering

itstack-demo-design-3-00└ ─ ─ the SRC └ ─ ─ the main └ ─ ─ Java └ ─ ─ org. Itstack. The demo, the design ├ ─ ─ ceilling │ ├ ─ ─ LevelOneCeiling. Java │ └ ─ ─ LevelTwoCeiling. Java ├ ─ ─ coat │ ├ ─ ─ DuluxCoat. Java │ └ ─ ─ LiBangCoat. Java │ └ ─ ─ LevelTwoCeiling. Java ├ ─ ─ floor │ ├ ─ ─ DerFloor. Java │ └ ─ ─ ├─ ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ JavaCopy the code

In the simulation project to provide the materials needed in the decoration; Ceilling, coat, floor, tile. (The actual decoration materials are much more than this)

2. Scenario description

2.1 Material Interfaces

public interface Matter {

    String scene(a);      / / the scene; Floor, tile, paint, ceiling

    String brand(a);      / / brand

    String model(a);      / / type

    BigDecimal price(a);  / / price

    String desc(a);       / / description

}
Copy the code
  • The material interface provides basic information to ensure that all decoration materials can be obtained according to uniform standards.

2.2 ceiling (between)

Level of the top

public class LevelOneCeiling implements Matter {

    public String scene(a) {
        return "Ceiling";
    }

    public String brand(a) {
        return "Bring your own decoration company.";
    }

    public String model(a) {
        return "Top one";
    }

    public BigDecimal price(a) {
        return new BigDecimal(260);
    }

    public String desc(a) {
        return "Modeling is only one level lower, only one level of ceiling, generally 120-150mm from the top."; }}Copy the code

To the top of the secondary

public class LevelTwoCeiling  implements Matter {

    public String scene(a) {
        return "Ceiling";
    }

    public String brand(a) {
        return "Bring your own decoration company.";
    }

    public String model(a) {
        return "Second order top";
    }

    public BigDecimal price(a) {
        return new BigDecimal(850);
    }

    public String desc(a) {
        return "For two levels of suspended ceiling, the height of the secondary suspended ceiling is generally lowered by 20cm. If the height is very high, the thickness of each level can also be increased."; }}Copy the code

2.3 paint (coat)

dulux

public class DuluxCoat  implements Matter {

    public String scene(a) {
        return "Paint";
    }

    public String brand(a) {
        return "Dulux";
    }

    public String model(a) {
        return "Second generation";
    }

    public BigDecimal price(a) {
        return new BigDecimal(719);
    }

    public String desc(a) {
        return "Dulux is the leading architectural decoration paint brand of Akzonobel. Its products are sold in 100 countries and 50 million households use Dulux paint every year."; }}Copy the code

Nippon

public class LiBangCoat implements Matter {

    public String scene(a) {
        return "Paint";
    }

    public String brand(a) {
        return "The nation";
    }

    public String model(a) {
        return "Default level";
    }

    public BigDecimal price(a) {
        return new BigDecimal(650);
    }

    public String desc(a) {
        return "Nippon always aims to develop green products, pay attention to high-tech and high quality, and constantly promote scientific research and development with technical force to meet consumer demand."; }}Copy the code

2.4 the floor (floor)

del

public class DerFloor implements Matter {

    public String scene(a) {
        return "Floor";
    }

    public String brand(a) {
        return "Del (Der)";
    }

    public String model(a) {
        return "A+";
    }

    public BigDecimal price(a) {
        return new BigDecimal(119);
    }

    public String desc(a) {
        return "DER DER Group is the world's leading professional wood flooring manufacturer and supplier of home and public flooring for the Beijing 2008 Olympic Games."; }}Copy the code

iconography

public class ShengXiangFloor implements Matter {

    public String scene(a) {
        return "Floor";
    }

    public String brand(a) {
        return "Holy elephant";
    }

    public String model(a) {
        return "Level";
    }

    public BigDecimal price(a) {
        return new BigDecimal(318);
    }

    public String desc(a) {
        return "Shengxiang flooring is a famous brand in Chinese flooring industry. Holy floor has China well-known trademark, China famous brand, national inspection exemption, China environmental mark certification and other honors.; }}Copy the code

2.5 floor tile (tile)

Dong peng

public class DongPengTile implements Matter {

    public String scene(a) {
        return "Tile";
    }

    public String brand(a) {
        return "Dongpeng Ceramic Tile";
    }

    public String model(a) {
        return "10001";
    }

    public BigDecimal price(a) {
        return new BigDecimal(102);
    }

    public String desc(a) {
        return "Dongpeng ceramic takes quality to build brand, technology to promote brand, word of mouth to spread brand as the purpose, in 2014, the brand value of 13.235 billion yuan, ranked the first place in the ceramic industry.; }}Copy the code

Marco Polo

public class MarcoPoloTile implements Matter {

    public String scene(a) {
        return "Tile";
    }

    public String brand(a) {
        return "MARCO POLO";
    }

    public String model(a) {
        return "Default";
    }

    public BigDecimal price(a) {
        return new BigDecimal(140);
    }

    public String desc(a) {
        return "Marco Polo" brand was born in 1996, as the earliest brand of building pottery in China, with "cultural ceramics" occupy the market, enjoy the reputation of "antique brick supreme".; }}Copy the code
  • Above is this decoration company to provideDecoration and distribution listNext, we will use different materials to combine different package services through cases.

Five, with a lump of code implementation

There is no logic that ifelse can't solve. If not, add a line!

In each chapter, we will use such a straightforward way to realize the function, and optimize it through the design mode. This code structure is also very simple, there is no complex class relationship structure, are straight-forward code. In addition to the fact that we often point out that such code does not extend well, it is possible to do some sample projects.

1. Engineering structure

itstack-demo-design-3-01└ ─ ─ the SRC └ ─ ─ the main └ ─ ─ Java └ ─ ─ org. Itstack. Demo. The design └ ─ ─ DecorationPackageController. JavaCopy the code

A class of several thousand lines of code have you ever seen ho? Today let you have a taste of such potential class!

2. Ifelse implementation requirements

public class DecorationPackageController {

    public String getMatterList(BigDecimal area, Integer level) {

        List<Matter> list = new ArrayList<Matter>(); // Decoration list
        BigDecimal price = BigDecimal.ZERO;          // Decoration price

        // Luxury European style
        if (1 == level) {

            LevelTwoCeiling levelTwoCeiling = new LevelTwoCeiling(); // There is a ceiling
            DuluxCoat duluxCoat = new DuluxCoat();                   // Paint, Dulux
            ShengXiangFloor shengXiangFloor = new ShengXiangFloor(); // Floor, holy image

            list.add(levelTwoCeiling);
            list.add(duluxCoat);
            list.add(shengXiangFloor);

            price = price.add(area.multiply(new BigDecimal("0.2")).multiply(levelTwoCeiling.price()));
            price = price.add(area.multiply(new BigDecimal("1.4")).multiply(duluxCoat.price()));
            price = price.add(area.multiply(shengXiangFloor.price()));

        }

        // Light luxury countryside
        if (2 == level) {

            LevelTwoCeiling levelTwoCeiling = new LevelTwoCeiling(); // There is a ceiling
            LiBangCoat liBangCoat = new LiBangCoat();                // Paint, Nippon
            MarcoPoloTile marcoPoloTile = new MarcoPoloTile();       // Floor tiles, Marco Polo

            list.add(levelTwoCeiling);
            list.add(liBangCoat);
            list.add(marcoPoloTile);

            price = price.add(area.multiply(new BigDecimal("0.2")).multiply(levelTwoCeiling.price()));
            price = price.add(area.multiply(new BigDecimal("1.4")).multiply(liBangCoat.price()));
            price = price.add(area.multiply(marcoPoloTile.price()));

        }

        // Modern simplicity
        if (3 == level) {

            LevelOneCeiling levelOneCeiling = new LevelOneCeiling();  // There is a ceiling
            LiBangCoat liBangCoat = new LiBangCoat();                 // Paint, Nippon
            DongPengTile dongPengTile = new DongPengTile();           // Floor tile, Dong Peng

            list.add(levelOneCeiling);
            list.add(liBangCoat);
            list.add(dongPengTile);

            price = price.add(area.multiply(new BigDecimal("0.2")).multiply(levelOneCeiling.price()));
            price = price.add(area.multiply(new BigDecimal("1.4")).multiply(liBangCoat.price()));
            price = price.add(area.multiply(dongPengTile.price()));
        }

        StringBuilder detail = new StringBuilder("\r\n-------------------------------------------------------\r\n" +
                "Decoration List" + "\r\n" +
                "Package level:" + level + "\r\n" +
                "Package price:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + "Yuan \ r \ n" +
                "Floor area:" + area.doubleValue() + "Square \ r \ n" +
                "List of Materials: \r\n");

        for (Matter matter: list) {
            detail.append(matter.scene()).append(":").append(matter.brand()).append("、").append(matter.model()).append(Square meter price:).append(matter.price()).append("The yuan. \n");
        }

        returndetail.toString(); }}Copy the code
  • The first problem this code needs to solve is to connect the income parameter; Decoration area, decoration level, according to different types of decoration level to choose different materials.
  • Second, you can see each section in the implementation processifBlock, all contain different materials (Suspended ceiling, secondary roof, paint, Bond, floor tile, Marco Polo), and finally generate the decoration list and decoration cost.
  • Finally, a method is provided to obtain the details of the decoration, which is returned to the caller to know the decoration list.

3. Test and verify

Next, we verify the interface services through junit unit tests, emphasizing that routine single-test writing can better improve the robustness of the system.

Writing test classes:

@Test
public void test_DecorationPackageController(a){
    DecorationPackageController decoration = new DecorationPackageController();
    // Luxury European style
    System.out.println(decoration.getMatterList(new BigDecimal("132.52"),1));
    // Light luxury countryside
    System.out.println(decoration.getMatterList(new BigDecimal("98.25"),2));
    // Modern simplicity
    System.out.println(decoration.getMatterList(new BigDecimal("85.43"),3));
}
Copy the code

Results:

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- to decorate level of listing package:1Package price:198064.39Yuan Housing area:132.52Square meter material list: ceiling: decoration company, two top, square meter price:850Yuan. Paint: Dulux, the second generation, square meter price:719Yuan. Floor: Holy image, level 1, square meter price:318Yuan. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- to decorate level of listing package:2Package price:119865.00Yuan Housing area:98.25Square meter material list: ceiling: decoration company, two top, square meter price:850Yuan. Paint: Nippon, default level, square meter price:650Yuan. Floor tile: MARCO POLO, default, square meter price:140Yuan. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- to decorate level of listing package:3Package price:90897.52Yuan Housing area:85.43Square meter material list: ceiling: decoration company, a top, square meter price:260Yuan. Paint: Nippon, default level, square meter price:650Yuan. Floor tile: Dongpeng ceramic tile,10001Square meter price:102Yuan. Process finished with exit code0
Copy the code
  • See the output of this result, has been a decoration company to provide a quotation of the feeling. The above paragraph is usedifelseThe way to achieve the code, so far has met our perhaps function. However, with the rapid development of business requirements of the boss, many packages will be provided for different apartment types. This implementation code would quickly grow to thousands of lines, and even in the midst of tinkering it would become a sticking plaster.

The builder pattern refactors the code

The next step is to use the Builder pattern for code optimization, which is a minor refactoring.

The main problem of builder mode is that in software system, sometimes we are faced with the creation of “a complex object”, which is usually composed of sub-objects of each part by a certain process. The pieces of this complex object often face significant changes due to changing requirements, but the process of putting them together is relatively stable.

Here we will hand over the build process to the creator class, who will use our build kit to build different decoration packages.

1. Engineering structure

itstack-demo-design-3-02└ ─ ─ the SRC ├ ─ ─ the main │ └ ─ ─ Java │ └ ─ ─ org. Itstack. The demo, the design │ ├ ─ ─ Builder. Java │ ├ ─ ─ DecorationPackageMenu. Java │ └ ─ ─ IMenu. Java └ ─ ─ the test └ ─ ─ Java └ ─ ─ org. Itstack. The demo, the design, test └ ─ ─ ApiTest. JavaCopy the code

Builder model structure

There are three core classes and one test class in the project, and the core class is the concrete implementation of the Builder pattern. Compared to the ifelse implementation, there are two extra classes. The specific functions are as follows;

  • BuilderThe builder class concrete various assemblies are implemented by this class.
  • DecorationPackageMenu, it isIMenuThe implementation class of the interface is primarily the host for the fillers in the construction process. Equivalent to this is a set of bearing material and the creator of the connection between the content.

Ok, so I’m going to talk about the implementation of each of these classes.

2. Code implementation

2.1 Define interfaces for decoration packages

public interface IMenu {

    IMenu appendCeiling(Matter matter); / / ceiling

    IMenu appendCoat(Matter matter);    / / coating

    IMenu appendFloor(Matter matter);   / / floor

    IMenu appendTile(Matter matter);    / / floor tile

    String getDetail(a);                 / / detail

}
Copy the code
  • The interface class defines the method of filling each material;Condole top,coating,The floor,Floor tileAnd finally provide a way to get the full details.

2.2 Realization of decoration package

public class DecorationPackageMenu implements IMenu {

    private List<Matter> list = new ArrayList<Matter>();  // Decoration list
    private BigDecimal price = BigDecimal.ZERO;      // Decoration price

    private BigDecimal area;  / / area
    private String grade;     // Decoration level; Luxurious European style, light luxury pastoral, modern simplicity

    private DecorationPackageMenu(a) {}public DecorationPackageMenu(Double area, String grade) {
        this.area = new BigDecimal(area);
        this.grade = grade;
    }

    public IMenu appendCeiling(Matter matter) {
        list.add(matter);
        price = price.add(area.multiply(new BigDecimal("0.2")).multiply(matter.price()));
        return this;
    }

    public IMenu appendCoat(Matter matter) {
        list.add(matter);
        price = price.add(area.multiply(new BigDecimal("1.4")).multiply(matter.price()));
        return this;
    }

    public IMenu appendFloor(Matter matter) {
        list.add(matter);
        price = price.add(area.multiply(matter.price()));
        return this;
    }

    public IMenu appendTile(Matter matter) {
        list.add(matter);
        price = price.add(area.multiply(matter.price()));
        return this;
    }

    public String getDetail(a) {

        StringBuilder detail = new StringBuilder("\r\n-------------------------------------------------------\r\n" +
                "Decoration List" + "\r\n" +
                "Package level:" + grade + "\r\n" +
                "Package price:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + "Yuan \ r \ n" +
                "Floor area:" + area.doubleValue() + "Square \ r \ n" +
                "List of Materials: \r\n");

        for (Matter matter: list) {
            detail.append(matter.scene()).append(":").append(matter.brand()).append("、").append(matter.model()).append(Square meter price:).append(matter.price()).append("The yuan. \n");
        }

        returndetail.toString(); }}Copy the code
  • The realization of every method in the decoration package will bethis, also can be very convenient for continuous filling materials.
  • At the same time in the filling will also be calculated according to the material under the number of square meters of quotation, ceiling and coating in accordance with the number of square meters of appropriate times changshu calculation.
  • Finally, it also provides a unified method to obtain the details of the decoration list.

2.3 Builder’s method

public class Builder {

    public IMenu levelOne(Double area) {
        return new DecorationPackageMenu(area, "Luxury European style")
                .appendCeiling(new LevelTwoCeiling())    // There is a ceiling
                .appendCoat(new DuluxCoat())             // Paint, Dulux
                .appendFloor(new ShengXiangFloor());     // Floor, holy image
    }

    public IMenu levelTwo(Double area){
        return new DecorationPackageMenu(area, "Light luxury countryside")
                .appendCeiling(new LevelTwoCeiling())   // There is a ceiling
                .appendCoat(new LiBangCoat())           // Paint, Nippon
                .appendTile(new MarcoPoloTile());       // Floor tiles, Marco Polo
    }

    public IMenu levelThree(Double area){
        return new DecorationPackageMenu(area, "Modern simplicity")
                .appendCeiling(new LevelOneCeiling())   // There is a ceiling
                .appendCoat(new LiBangCoat())           // Paint, Nippon
                .appendTile(new DongPengTile());        // Floor tile, Dong Peng}}Copy the code
  • The use of the builder is already very easy, the unified construction method, through different materials filled out different decoration style;Luxury european-style,Light the luxury of rural,Contemporary and contractedIf business expansion in the future can also configure this part of the content to the database automatically generated. But the whole idea can also be constructed using the creator pattern.

3. Test and verify

Writing test classes:

@Test
public void test_Builder(a){
    Builder builder = new Builder();
    // Luxury European style
    System.out.println(builder.levelOne(132.52D).getDetail());
    // Light luxury countryside
    System.out.println(builder.levelTwo(98.25D).getDetail());
    // Modern simplicity
    System.out.println(builder.levelThree(85.43D).getDetail());
}
Copy the code

Results:

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- to decorate listing package level: luxury european-style package price:198064.39Yuan Housing area:132.52Square meter material list: ceiling: decoration company, two top, square meter price:850Yuan. Paint: Dulux, the second generation, square meter price:719Yuan. Floor: Holy image, level 1, square meter price:318Yuan. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- to decorate listing package level: excessive rural package price:119865.00Yuan Housing area:98.25Square meter material list: ceiling: decoration company, two top, square meter price:850Yuan. Paint: Nippon, default level, square meter price:650Yuan. Floor tile: MARCO POLO, default, square meter price:140Yuan. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- to decorate listing package level: contemporary and contracted package price:90897.52Yuan Housing area:85.43Square meter material list: ceiling: decoration company, a top, square meter price:260Yuan. Paint: Nippon, default level, square meter price:650Yuan. Floor tile: Dongpeng ceramic tile,10001Square meter price:102Yuan. Process finished with exit code0
Copy the code
  • The test results are the same, and the invocation is similar. But the current code structure makes it easy to expand your business. Instead of writing all the code as usualifelseThe inside.

Seven,

  • Through the use of the builder pattern above, you can already glean a few lessons. That is when to choose such a design pattern, when:Some basic materials do not change, but their combination often changes, you can choose such a design pattern to build your code.
  • This design pattern meets the principle of single responsibility, reusable technology, builder independence, easy extension, and easy control of detail risk. But at the same time, when there are too many materials and too many combinations, the continuous expansion of the class can also cause difficult maintenance problems. However, this design structure model can abstract repetitive content into the database and configure it as needed. This reduces a lot of duplication in the code.
  • The design pattern can bring you some ideas, but in the usual development how to clearly refine the building module in line with this idea, is more difficult. It takes some practice and more projects to get that experience. Sometimes your code is written well, often is forced, complex business frequent change, constant challenge!

Recommended reading

  • Relearn the Java design pattern: Practice the Factory Method pattern
  • Relearn Java design patterns: Practice abstract Factory patterns
  • Java Development Architecture: Introduction to domain-driven Design DDD Landing
  • Java Development Architecture: DDD Model Domain-level decision Tree Service Design
  • Java development architecture: domain-driven design architecture builds microservices based on SpringCloud