State mode of design mode series

stay State mode of design mode The state mode is introduced in, leaving a suspense about how to completely kill if/else. This paper mainly solves this problem.

State transition and maintenance

In the previous article, the maintenance of state is in the context, which inevitably uses if/else for judgment. If the maintenance of state is placed in the state processing class, the use of if/else in Dalian can be avoided.

Maintain state in the state processing class: when each state object has processed the function corresponding to its own state, specify the subsequent state as needed, so that the application can correctly process the subsequent requests.

Sequence diagram

Like the above articles, class diagrams mainly focus on sequence diagrams, which can be easily understood.

The malicious voting status and blacklist status are similar to this, and are not drawn in the sequence diagram.

code implementation

Client code

First look at the client. Compare the use mode with the no use mode. The implementation of no use mode is in State mode of design mode.

        Console.WriteLine("Operation results without mode:");
        VoteManager voteManager = new VoteManager();
        for (int i = 0; i < 10; i++)
        {
            voteManager.Vote("Burning", "sxy");
        }

        Console.WriteLine("\n");
        Console.WriteLine("Running results using state mode:");
        VoteManagerContext vmc = new VoteManagerContext();  

       for (int i = 0; i < 10; i++)
       {
            vmc.Vote("Burning", "sxy");
       }

Context implementation

Since the maintenance of the state is placed in the state processing class, the context does not have the necessary if/else. The user status dictionary is mainly added to facilitate status maintenance.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    internal class VoteManagerContext
    {
        // Voting status
        private VoteState voteState;

        // Voting user voting options
        private Dictionary<String, String> dictionaryVote = new Dictionary<String, String>();

        // Number of voting users
        private Dictionary<String, int> dictionaryVoteCount = new Dictionary<string, int>();

        // Voting user status
        private Dictionary<String, VoteState> dictionaryVoteState = new Dictionary<string, VoteState>();

        //Number of votes saved
        private int count = 0;

        public Dictionary<String, String> getDictionaryVote()
        {
            return dictionaryVote;
        }

        public Dictionary<String, VoteState> getDictionaryVoteState()
        {
            return dictionaryVoteState;
        }

        public Dictionary<String, int> getDictionaryVoteCount()
        {
            return dictionaryVoteCount;
        }

        public void Vote(String user, String item)
        {
            bool contain = dictionaryVoteState.ContainsKey(user);
            if (!contain)
            {
                voteState = new NormalVoteState();
                dictionaryVoteState.Add(user, voteState);
            }
            voteState = dictionaryVoteState[user];
            count = count + 1;
            if (!dictionaryVoteCount.ContainsKey(user))
            {
                dictionaryVoteCount.Add(user, count);

            }
            dictionaryVoteCount[user] = count;
            voteState.Vote(user, item, this);
        }
    }
}

Normal voting status

Add maintenance of subsequent status (repeated voting).

namespace ConsoleApp1
{
    internal class NormalVoteState : VoteState
    {
        public void Vote(string user, string item, VoteManagerContext voteManagerContext)
        {
            Console.WriteLine("Successful voting");
            Dictionary<String, int> dictionaryVoteCount = voteManagerContext.getDictionaryVoteCount();
            if (dictionaryVoteCount[user] == 1)
            {
                voteManagerContext.getDictionaryVote().Add(user, item);
            }
            Dictionary<String, int> voteCount =  voteManagerContext.getDictionaryVoteCount();
            if (voteCount[user] < 3)
            {
                voteManagerContext.getDictionaryVoteState()[user] =  new RepeatNoteState();
            }
        }
    }
}

Repeat voting status

Add maintenance of subsequent status (malicious voting).

namespace ConsoleApp1
{
    internal class RepeatNoteState : VoteState
    {
        public void Vote(string user, string item, VoteManagerContext voteManagerContext)
        {
            Console.WriteLine("Please do not vote again");
            Dictionary<String, int> voteCount = voteManagerContext.getDictionaryVoteCount();
            if (voteCount[user] < 8)
            {
                voteManagerContext.getDictionaryVoteState()[user] = new SpiteVoteState();
            }
        }
    }
}

Malicious voting status

Add maintenance of subsequent status (blacklist).

namespace ConsoleApp1
{
    internal class SpiteVoteState : VoteState
    {
        public void Vote(string user, string item, VoteManagerContext voteManagerContext)
        {
            bool contain = voteManagerContext.getDictionaryVote().ContainsKey(user);
            if (contain)
            {
                voteManagerContext.getDictionaryVote().Remove(user);
            }
            Console.WriteLine("Malicious voting behavior, disqualification");
            Dictionary<String, int> voteCount = voteManagerContext.getDictionaryVoteCount();
            if (voteCount[user] >= 7)
            {
                voteManagerContext.getDictionaryVoteState()[user] = new BlackVoteState();
            }
        }
    }
}

Blacklist status

There is no need to add subsequent status maintenance.

namespace ConsoleApp1
{
    internal class BlackVoteState : VoteState
    {
        public void Vote(string user, string item, VoteManagerContext voteManagerContext)
        {
            Console.WriteLine("Join the blacklist and prohibit logging into the system");
        }
    }
}

Operation results

Exactly the same, the amount of code increases a lot, while avoiding Dalian's if/else condition judgment.

extend

8 to 9 times. Give me a chance. It is forbidden to log in to the system within 3 days. Add the corresponding class and modify the subsequent state of the following previous state class. Here are the newly added classes.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    internal class BlackVWarnoteState : VoteState
    {
        public void Vote(string user, string item, VoteManagerContext voteManagerContext)
        {
            bool contain = voteManagerContext.getDictionaryVote().ContainsKey(user);
            if (contain)
            {
                voteManagerContext.getDictionaryVote().Remove(user);
            }
            Console.WriteLine("It is forbidden to log in to the system within 3 days");
            Dictionary<String, int> voteCount = voteManagerContext.getDictionaryVoteCount();
            if (voteCount[user]  >= 9)
            {
                voteManagerContext.getDictionaryVoteState()[user] = new BlackVoteState();
            }
        }
    }
}

Operation results

essence

Separate and select behaviors based on state

Download last

if/else can also be eliminated through factory + status, and it is more perfect.

official account

More content, welcome to my WeChat official account: the ruthless swordsman on the midnight of Pinellia.

Keywords: Java Design Pattern

Added by ld0121 on Sun, 09 Jan 2022 10:49:59 +0200