Explain the design pattern in a simple way - understand the command pattern from the game

First, the concept of command mode

    Command mode, as the name implies, is to issue commands to objects to perform specified operations. Specifically, it sends a request in the form of a command to the calling object, and then the calling object transmits the command to the object that needs to process the command and lets the target object execute the command.

    The old rules, take a ball game as an example, usually a team is in a game, and the tactics are constantly changing as the game progresses and the situation on the field needs to be changed. Then the coach's instruction to change the tactic is an order, the tactic is the call object in the middle, and the player is the target object to execute the order. Let's simply imagine that if there is no tactics, the coach needs to command the 11 people on the field individually, what do you do on the 1st, what do you do on the 2nd... After a game, the coach is crazy. With tactics in place, the coach only needs to say: Execute the first set of operations immediately. Then the players on the field understood, and after a game, they were relaxed and comfortable.

2. Usage scenarios

    Handle variable behaviors to achieve loose coupling between instructions and behaviors.

3. Structure

    

    From the UML diagram above we can see that the command pattern consists of three parts:

        1. Target object (Action implementation class): The object (player) that executes the command.

        2. Calling object (implementation class of Command): command set (tactics).

        3. Requester: The object who issued the command.

4. Realization

    Having said so much, let's go to the dry goods.

1. Define the target object

    The tactical actions that players have on the field are actually the same, but the specific actions that each player needs to perform at different times are different, so I need an action package (Action interface), which contains the actions of all players.

public interface Action {
    void attack();  //进攻
    void defend();  //防守
    void relax();   //保持体力
}

    Isn't it very simple, there are three actions in total. Next we started training the players to understand the three movements.

public class Player1 implements Action {
    @Override
    public void attack() {
        System.out.println("1号球员,进攻!");
    }

    @Override
    public void defend() {
        System.out.println("1号球员,防守!");
    }

    @Override
    public void relax() {
        System.out.println("1号球员,保持体力!");
    }
}

    Well, player No. 1 has already grasped the essentials of action, players No. 2 and 3 are similar to him, so I will not teach them one by one.

2. Define the calling object

    Next, we need to complete the call object, that is, tactical training. First, an interface is required. This interface contains a method for executing commands. When the orderer wants to call this execution method, the target object will execute the corresponding method.

public interface Command {
    void executed();    //执行方法
}

    It's that simple, and then start laying out specific tactics. The first is tactic number one:

public class FirstTactics implements Command {

    private Map<Class<? extends Action>, Action> playerMap;

    public FirstTactics(Map<Class<? extends Action>, Action> playerMap) {
        this.playerMap = playerMap;
        System.out.println("开始执行第一套作战方案!");
    }

    @Override
    public void executed() {
        playerMap.forEach((s, o) -> o.attack());
    }

    Tactic No. 1 accepts a map, which is a collection of players on the field, and then executed, that is, the tactical execution method is to let all players participate in the offense. Then take a look at the second tactic:

public class SecondTactics implements Command {

    private Map<Class<? extends Action>, Action> playerMap;

    public SecondTactics(Map<Class<? extends Action>, Action> playerMap) {
        this.playerMap = playerMap;
        System.out.println("开始执行第二套作战方案!");
    }


    @Override
    public void executed() {
        Action player1 = playerMap.get(Player1.class);
        Action player2 = playerMap.get(Player2.class);
        Action player3 = playerMap.get(Player2.class);
        player1.attack();
        player2.defend();
        player3.relax();
    }

    Tactic No. 2 also accepts a set of all players, and then it gives different instructions to different players.

3. Requester

    Finally, let's take a look at how the command mode works. Well, the coach is about to start issuing orders.

public class Coach {
    public static void main(String[] args) {
//        Player1 player1 = new Player1();
//        Player2 player2 = new Player2();
//        Player3 player3 = new Player3();
//
//        player1.attack();
//        player2.attack();
//        player3.attack();
//
//        player1.attack();
//        player2.defend();
//        player3.relax();
//
//        player1.attack();
//        player2.attack();
//        player3.attack();

        Map<Class<? extends Action>, Action> playerMap = new HashMap<>();
        playerMap.put(Player1.class, new Player1());
        playerMap.put(Player2.class, new Player2());
        playerMap.put(Player3.class, new Player3());

        new FirstTactics(playerMap).executed();
        new SecondTactics(playerMap).executed();
        new FirstTactics(playerMap).executed();

    }
}

    What's in the comments are the steps we need to do to do the same thing without using command mode. With only 3 players we can already see it's bloated, so just ignore it.

    We first need to add all the players on the field to a map similar to the instruction library. Then pass the player into the tactical order to get the desired execution effect. Let's run it.

    The result is obvious, as long as we find the corresponding tactics, the players will execute according to the instructions laid out in the tactics, this is the command mode.

5. Advantages

    Through the above comparison, I believe everyone can clearly see that the command mode reduces the degree of system coupling, and if there are new commands (tactics) or changes in tactics, we can easily implement them.

6. Limitations

    If there are too many commands, there may be too many call objects in the system, which may be the only deficiency of the command mode that can be found. Of course, the same sentence: there is no perfect pattern in the world, every design pattern has its place, as long as we use it properly, then the decorator pattern can help us write beautiful and elegant code.

Attached source code address: https://gitee.com/jack90john/command

------------------------------------------------------------------------------

Welcome to pay attention to my personal public account and push the latest articles

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324435703&siteId=291194637