Re learn the Java design mode: the actual command mode "simulate the eight major cuisines of high-end restaurants, and the cooking scene of the single chef at the second place"


Author: little brother Fu
Blog: https://bugstack.cn -Original series of special articles

Precipitation, sharing, growth, so that they and others can have a harvest! 😄

1, Foreword

The importance of persistence

Beginners are often very ignorant of programming, almost in the process of learning will encounter a variety of problems, even if other people run good code, but you just write the wrong report. But the good thing is that you stick to it, or you may not see the article. Time and growth are related to each other. You can see how beautiful the destination is if you stick to it for a long time. But if you waste the opportunity to work hard again and again, you will also miss a lot of opportunities, because your road has changed. Persist in learning, strive to grow, and persevere in paying will surely yield.

The importance of learning methods

Will not learn will often delay a lot of time, and there is no considerable harvest. But sometimes it's because of laziness, especially learning videos, books, technical documents, etc. if you just read them, but it's not verified by actual operation, it's really difficult to absorb other people's knowledge for yourself, even if you feel like it will soon be forgotten. Sometimes people will come to you and say, "I don't know. You tell me first, and then I'll learn." But did you learn later?

How long are you willing to pay for a knowledge blind area

Do you sometimes have such words in your mind? It's too difficult for me to find someone to help you and give up. In fact, anyone may encounter a very difficult problem, which can also be asked for consultation. However, if you don't find the answer repeatedly in your brain before this, then you won't form a convex knowledge tree in your brain. Without this learning process, you will also lack the opportunity to consult various materials to fill your brain with knowledge, even if you ask for the answer, you will eventually forget because of the passage of time.

2, Development environment

  1. JDK 1.8
  2. Idea + Maven
  3. Involving three projects, we can pay attention to the official account number: bugstack wormhole stack , reply to the source code download and obtain (open the obtained link and find the No. 18)
engineering describe
itstack-demo-design-14-01 Use a bunch of code to realize business requirements
itstack-demo-design-14-02 Optimize code structure through design pattern, increase scalability and maintainability

3, Command mode introduction

Command mode is relatively less used in our usual Internet development, but such a mode is often used in our daily life, that is, Ctrl+C, Ctrl+V. Of course, if you have developed some desktop applications, you will also feel the application scenarios of this design mode. From the perspective of such a pattern, it can be thought that this is to separate the logical implementation from the operation request and reduce the coupling for convenient expansion.

Command mode is one of behavior modes. Command objects can be passed to callers in a data-driven way by using constructors. The caller then provides the corresponding implementation to provide the operation method for command execution. You may feel that this part has some sparseness. You can understand the implementation of the code and be proficient in practice.

There are several important points in the implementation of this design pattern as follows:;

  1. Abstract command class; declare interfaces and methods for executing commands
  2. Specific command implementation class; specific implementation of interface class can be a set of similar behavioral logic
  3. Implementer; that is, the concrete implementation class to implement the command
  4. The caller; the specific operator who processes and implements the order, and is responsible for providing the order service to the outside

4, Case scenario simulation

In this case, we simulate ordering food in a restaurant and giving it to the chef 👨‍🍳 Cooking scene

The core logic of the command scenario is that the caller does not need to care about the specific logic implementation. In this scenario, the ordering personnel only need to give a waiter a variety of dishes that need to be ordered, and the waiter then gives the dishes to the chefs for cooking. That is to say, the ordering personnel do not need to communicate with the chefs, only need to give orders in a unified environment.

In this scene, you can see that there are different dishes; Shandong (Shandong cuisine), Sichuan (Sichuan cuisine), Jiangsu (Jiangsu cuisine), Guangdong (Guangdong cuisine), Fujian (Fujian Cuisine), Zhejiang (Zhejiang cuisine), Hunan (Hunan cuisine), and there will be different chefs for each dish 👩‍🍳 Cook. Customers don't care who cooks, and chefs don't care who orders. The customer only cares about serving early, and the chef only cares about how many dishes are left to cook. And the process of connection between them is completed by sophomore.

So in such a simulation scenario, you can think first 🤔 Which part is the disassembly of the command mode, which part is the caller of the command and the implementation logic of the command.

5, Using a pile of code to realize

Without considering the design pattern, it is enough to have a class for such a point and single system

For such a complex scenario, if you don't know the design pattern, you can achieve the goal. However, it will become very coupling and difficult to expand for the subsequent extension of dishes, chef implementation and how to call.

1. Engineering structure

itstack-demo-design-14-01
└── src
    └── main
        └── java
            └── org.itstack.demo.design
                └── XiaoEr.java
  • There is only one class of hotel waiter, through which the whole order logic of different dishes can be realized.

2. Code implementation

public class XiaoEr {

    private Logger logger = LoggerFactory.getLogger(XiaoEr.class);

    private Map<Integer, String> cuisineMap = new ConcurrentHashMap<Integer, String>();

    public void order(int cuisine) {
        // Guangdong (Cantonese cuisine)
        if (1 == cuisine) {
            cuisineMap.put(1, "Guangdong chef, cooking Shandong cuisine, the largest cuisine in the palace, taking the flavor of Confucius Mansion as the leader");
        }

        // Jiangsu (Jiangsu cuisine)
        if (2 == cuisine) {
            cuisineMap.put(2, "Jiangsu chefs, cooking Su cuisine, the second largest cuisine in the palace, the most popular cuisine in ancient and modern state banquets.");
        }

        // Shandong (Shandong cuisine)
        if (3 == cuisine) {
            cuisineMap.put(3, "Shandong chef, cooking Shandong cuisine, the largest cuisine in the palace, taking the flavor of Confucius as the leader.");
        }

        // Sichuan (Sichuan cuisine)
        if (4 == cuisine) {
            cuisineMap.put(4, "Sichuan chef, cooking Sichuan cuisine, the most distinctive cuisine in China, is also the largest folk cuisine.");
        }

    }

    public void placeOrder() {
        logger.info("Menu:{}", JSON.toJSONString(cuisineMap));
    }

}
  • Two methods are provided in the implementation of this class. One method is used to add the order() of dishes, and the other method is used to display the information placeOrder() of dishes.
  • It can be seen from the above that there are more if statements to judge the type of dishes to be added, so the subsequent maintenance of such code requires a lot of experience, and the actual logic may be more complex than this. It's very coupling to write in such a class.

6, Command mode refactoring code

The next step is to use command mode for code optimization, which is also a small refactoring.

The command mode can be divided into three layers: command, command implementer and command caller. When there are new dishes or chef extensions, they can be added under the specified class structure, and external calls will be very easy to expand.

1. Engineering structure

itstack-demo-design-14-02
└── src
    ├── main
    │   └── java
    │       └── org.itstack.demo.design
    │           ├── cook
    │           │    ├── impl
    │           │    │   ├── GuangDongCook.java
    │           │    │   ├── JiangSuCook.java
    │           │    │   ├── ShanDongCook.java
    │           │    │   └── SiChuanCook.java
    │           │    └── ICook.java
    │           ├── cuisine
    │           │    ├── impl
    │           │    │   ├── GuangDoneCuisine.java
    │           │    │   ├── JiangSuCuisine.java
    │           │    │   ├── ShanDongCuisine.java
    │           │    │   └── SiChuanCuisine.java
    │           │    └── ICuisine.java
    │           └── XiaoEr.java
    └── test
        └── java
            └── org.itstack.demo.test
                └── ApiTest.java

Command mode model structure

  • From the above figure, we can see that the whole system is divided into three parts: command implementation (dishes), logic implementation (cooks), and caller (sophomores). The above three aspects of implementation are the core content of command mode.
  • After such disassembly, the dishes and chefs can be expanded in many aspects. For the callers, this part is loosely coupled, and it is very easy to add implementation logic under the overall framework.

2. Code implementation

2.1 Abstract command definition (dish interface)

/**
 * Blog: https://bugstack.cn -  Precipitation, sharing, growth, so that they and others can have a harvest!
 * Official account: bugstack wormhole stack
 * Create by Fustack @ 2020
 *
 * Cuisine
 * 01,Shandong (Shandong cuisine) - the largest cuisine in the palace, with the flavor of Confucius as the leader.
 * 02,Sichuan (Sichuan cuisine) - the most distinctive cuisine in China, and also the largest folk cuisine.
 * 03,Jiangsu (Jiangsu cuisine) - the second largest cuisine in the palace, the most popular cuisine in the ancient and modern state banquet.
 * 04,Guangdong (Cantonese cuisine) - the second largest folk cuisine in China, the most influential Chinese cuisine abroad, can represent China.
 * 05,Fujian (Fujian Cuisine) - the representative cuisine of Hakka cuisine.
 * 06,Zhejiang (Zhejiang cuisine) - one of the oldest cuisines in China, the third largest cuisines in the palace.
 * 07,Hunan (Hunan cuisine) - the third largest folk cuisine.
 * 08,Anhui (Anhui cuisine) - a typical representative of Huizhou culture.
 */
public interface ICuisine {

    void cook(); // Cooking, making

}
  • This is the definition of the command interface class and provides a recipe. Later, four dishes will be selected for implementation.

2.2 specific command implementation (four dishes)

Guangdong (Cantonese cuisine)

public class GuangDoneCuisine implements ICuisine {

    private ICook cook;

    public GuangDoneCuisine(ICook cook) {
        this.cook = cook;
    }

    public void cook() {
        cook.doCooking();
    }

}

Jiangsu (Jiangsu cuisine)

public class JiangSuCuisine implements ICuisine {

    private ICook cook;

    public JiangSuCuisine(ICook cook) {
        this.cook = cook;
    }

    public void cook() {
        cook.doCooking();
    }

}

Shandong (Shandong cuisine)

public class ShanDongCuisine implements ICuisine {

    private ICook cook;

    public ShanDongCuisine(ICook cook) {
        this.cook = cook;
    }

    public void cook() {
        cook.doCooking();
    }

}

Sichuan (Sichuan cuisine)

public class SiChuanCuisine implements ICuisine {

    private ICook cook;

    public SiChuanCuisine(ICook cook) {
        this.cook = cook;
    }

    public void cook() {
        cook.doCooking();
    }

}
  • The above is the implementation of four dishes. In the implemented classes, a chef class (ICook) is added, and the operation command (cooking dishes) is carried out through the method provided by this class cook.doCooking().
  • The implementation process of the command can be added and supplemented according to the logic. At present, the abstraction here is relatively simple, just simulating a cooking process, which is equivalent to cooking dishes at the same time.

2.3 Abstract implementer definition (Chef interface)

public interface ICook {

    void doCooking();

}
  • What is defined here is the specific implementer of the command, which is the implementation of the chef's cooking instructions corresponding to the dishes.

2.4 specific implementation of implementer (four types of chefs)

Cantonese food, chef

public class GuangDongCook implements ICook {

    private Logger logger = LoggerFactory.getLogger(ICook.class);

    public void doCooking() {
        logger.info("Guangdong chef, cooking Shandong cuisine, the largest cuisine in the palace, taking the flavor of Confucius Mansion as the leader");
    }

}

Sauerkraut, chef

public class JiangSuCook implements ICook {

    private Logger logger = LoggerFactory.getLogger(ICook.class);

    public void doCooking() {
        logger.info("Jiangsu chefs, cooking Su cuisine, the second largest cuisine in the palace, the most popular cuisine in ancient and modern state banquets.");
    }

}

Shandong cuisine, chef

public class ShanDongCook implements ICook {

    private Logger logger = LoggerFactory.getLogger(ICook.class);

    public void doCooking() {
        logger.info("Shandong chef, cooking Shandong cuisine, the largest cuisine in the palace, taking the flavor of Confucius as the leader");
    }

}

Sauerkraut, chef

public class SiChuanCook implements ICook {

    private Logger logger = LoggerFactory.getLogger(ICook.class);

    public void doCooking() {
        logger.info("Sichuan chef, cooking Sichuan cuisine, the most distinctive cuisine in China, is also the largest folk cuisine.");
    }

}
  • Here are four different kinds of cooks 👩‍🍳 In this implementation process, the simulation logs, which is equivalent to informing the specific chef in the kitchen to cook the dishes.
  • As can be seen from the above, when we need to expand, it is very convenient to add. Each class has a single responsibility principle.

2.5 caller (sophomore)

public class XiaoEr {

    private Logger logger = LoggerFactory.getLogger(XiaoEr.class);

    private List<ICuisine> cuisineList = new ArrayList<ICuisine>();

    public void order(ICuisine cuisine) {
        cuisineList.add(cuisine);
    }

    public synchronized void placeOrder() {
        for (ICuisine cuisine : cuisineList) {
            cuisine.cook();
        }
        cuisineList.clear();
    }

}
  • In the specific implementation of the caller, the addition of dishes and menu execution cooking are provided. This process is the specific call of the command mode, and the specific call is made by passing in the dishes and cooks from the outside.

3. Test verification

3.1 write test class

@Test
public void test(){

    // Cuisine + chef; Guangdong (Cantonese), Jiangsu (Jiangsu), Shandong (Shandong), Sichuan (Sichuan)
    ICuisine guangDoneCuisine = new GuangDoneCuisine(new GuangDongCook());
    JiangSuCuisine jiangSuCuisine = new JiangSuCuisine(new JiangSuCook());
    ShanDongCuisine shanDongCuisine = new ShanDongCuisine(new ShanDongCook());
    SiChuanCuisine siChuanCuisine = new SiChuanCuisine(new SiChuanCook());

    // Order
    XiaoEr xiaoEr = new XiaoEr();
    xiaoEr.order(guangDoneCuisine);
    xiaoEr.order(jiangSuCuisine);
    xiaoEr.order(shanDongCuisine);
    xiaoEr.order(siChuanCuisine);

    // place an order
    xiaoEr.placeOrder();
}
  • Here, we can mainly observe the combination of dishes and chefs; new guangdonecouisine (New guangdongcook()); each specific command has a corresponding implementation class, which can be combined.
  • When the dishes and specific implementation definitions are completed, the waiter will make the operation order, xiaoEr.order (guangdoneuisine);, four dishes are added here, for the junior two.
  • Finally, the order is placed. This is the operation of specific command implementation, which is equivalent to passing the menu in small second-hand to the chef. Of course, deletion and cancellation can also be provided here, that is, the customer cancels one of his dishes.

3.2 test results

22:12:13.056 [main] INFO  org.itstack.demo.design.cook.ICook - Guangdong chef, cooking Shandong cuisine, the largest cuisine in the palace, taking the flavor of Confucius Mansion as the leader
22:12:13.059 [main] INFO  org.itstack.demo.design.cook.ICook - Jiangsu chefs, cooking Su cuisine, the second largest cuisine in the palace, the most popular cuisine in ancient and modern state banquets.
22:12:13.059 [main] INFO  org.itstack.demo.design.cook.ICook - Shandong chef, cooking Shandong cuisine, the largest cuisine in the palace, taking the flavor of Confucius as the leader
22:12:13.059 [main] INFO  org.itstack.demo.design.cook.ICook - Sichuan chef, cooking Sichuan cuisine, the most distinctive cuisine in China, is also the largest folk cuisine.

Process finished with exit code 0
  • From the above test results, we can see that the order we have given to the caller (sophomore) is implemented by different Chefs (cooking).
  • In addition, when we need different dishes or modifications, we can easily add and modify them. Under a single responsibility class, we can easily expand them.

7, Summary

  • From the above content and examples, it can be seen that the use scenario of command mode needs to be divided into three relatively large blocks: command, implementation and caller, and the split of these three blocks is also the key factor to choose the appropriate scenario. After such split, the logic can have the nature of a single responsibility and be easy to expand.
  • Compared with if statement, it reduces the coupling and facilitates the extension of other commands and implementations. But at the same time, such a design pattern also brings a problem, that is, under the combination of various commands and implementations, many implementation classes will be extended, which need to be managed.
  • The learning of design pattern must be practiced frequently, even if it is implemented in imitation at the beginning. After many times of practice, we can find some scenes that can be optimized, and gradually apply them to our own development. Improve your sense of code design, make the code structure more clear and easy to expand.

8, Recommended reading

Tags: Java Programming JDK Maven

Posted on Sun, 21 Jun 2020 22:13:43 -0400 by forced4