[GO] Comprendre le modèle d'état en comparant le code JavaScript et Java

introduction

Les détails et autres modèles seront écrits dans ** Comprendre les modèles de conception en comparant les implémentations en JavaScript et Java **. J'ai écrit un exemple de JavaScript en regardant Java. Nous ne tirons pas parti des différences de fonctionnalités telles que le type de classe / type de prototype, la force typée et les modificateurs d'accès. Notez s'il vous plaît.

Modèle d'état

Exprimer "l'état" en tant que classe état signifie "état (état des choses)"

Exemple d'implémentation en Java

Envisagez un système de sécurité sûr où l'état de la sécurité change avec le temps

Diagramme de classe

State.png

code

Main.java


public class Main {
    public static void main(String[] args) {
        SafeFrame frame = new SafeFrame("State Sample");
        while (true) {
            for (int hour = 0; hour < 24; hour++) {
                frame.setClock(hour);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {

                }
            }
        }
    }
}

Context.java


public interface Context {
    public abstract void setClock(int hour);
    public abstract void changeState(State state);
    public abstract void callSecurityCenter(String msg);
    public abstract void recordLog(String msg);
}

SafeFrame.java


import java.awt.Frame;
import java.awt.Label;
import java.awt.Color;
import java.awt.Button;
import java.awt.TextField;
import java.awt.TextArea;
import java.awt.Panel;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class SafeFrame extends Frame implements ActionListener, Context {
    private TextField textClock = new TextField(60);
    private TextArea textScreen = new TextArea(10, 60);
    private Button buttonUse = new Button("Utilisation sûre");
    private Button buttonAlarm = new Button("cloche d'urgence");
    private Button buttonPhone = new Button("Appel ambulatoire");
    private Button buttonExit = new Button("Fin");

    private State state = DayState.getInstance();

    public SafeFrame(String title) {
        super(title);
        setBackground(Color.lightGray);
        setLayout(new BorderLayout());

        add(textClock, BorderLayout.NORTH);
        textClock.setEditable(false);

        add(textScreen, BorderLayout.CENTER);
        textScreen.setEditable(false);

        Panel panel = new Panel();
        panel.add(buttonUse);
        panel.add(buttonAlarm);
        panel.add(buttonPhone);
        panel.add(buttonExit);

        add(panel, BorderLayout.SOUTH);

        pack();
        setVisible(true);

        buttonUse.addActionListener(this);
        buttonAlarm.addActionListener(this);
        buttonPhone.addActionListener(this);
        buttonExit.addActionListener(this);
    } 

    public void actionPerformed(ActionEvent e) {
        System.out.println(e.toString());
        if (e.getSource() == buttonUse) {
            state.doUse(this);
        } else if (e.getSource() == buttonAlarm) {
            state.doAlarm(this);
        } else if (e.getSource() == buttonPhone) {
            state.doPhone(this);
        } else if (e.getSource() == buttonExit) {
            System.exit(0);
        } else {
            System.out.println("?");
        }
    }

    public void setClock(int hour) {
        String clockstring = "L'heure actuelle est";

        if (hour < 10) {
            clockstring += "0" + hour + ":00";
        } else {
            clockstring += hour + ":00";
        }
        System.out.println(clockstring);
        textClock.setText(clockstring);
        state.doClock(this, hour);
    }

    public void changeState(State state) {
        System.out.println(this.state + "De" + state + "L'état a changé.");
        this.state = state;
    }

    public void callSecurityCenter(String msg) {
        textScreen.append("call! " + msg + "\n");
    }

    public void recordLog(String msg) {
        textScreen.append("record ... " + msg + "\n");
    }
}

State.java


public interface State {
    public abstract void doClock(Context context, int hour);
    public abstract void doUse(Context context);
    public abstract void doAlarm(Context context);
    public abstract void doPhone(Context context);
}

DayState.java


public class DayState implements State {
    private static DayState singleton = new DayState();
    
    private DayState() {

    }
    public static State getInstance() {
        return singleton;
    }
    public void doClock(Context context, int hour) {
        if (hour < 9 || 17 <= hour) {
            context.changeState(NightState.getInstance());
        }
    }
    public void doUse(Context context) {
        context.recordLog("Utilisation sûre(Jour)");
    }
    public void doAlarm(Context context) {
        context.callSecurityCenter("cloche d'urgence(Jour)");
    }
    public void doPhone(Context context) {
        context.callSecurityCenter("Appel normal(Jour)");
    }
    public String toString() {
        return "[Jour]";
    }
}

NightState.java


public class NightState implements State {
    private static NightState singleton = new NightState();

    private NightState() {

    }
    public static State getInstance() {
        return singleton;
    }
    public void doClock(Context context, int hour) {
        if (9 <= hour && hour < 17) {
            context.changeState(DayState.getInstance());
        }
    }
    public void doUse(Context context) {
        context.callSecurityCenter("Urgence: utilisez le coffre-fort la nuit!");
    }
    public void doAlarm(Context context) {
        context.callSecurityCenter("cloche d'urgence(Nuit)");
    }
    public void doPhone(Context context) {
        context.recordLog("Enregistrement des appels de nuit");
    }
    public String toString() {
        return "[Nuit]";
    }
}

Exemple d'implémentation en JavaScript

code

index.html


<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Modèle d'état</title>
	<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="main container flex">
	<input type="text" name="output" disabled="disabled">
	<textarea disabled="disabled"></textarea>
	<div class="button_area flex">
		<button>Utilisation sûre</button>
		<button>cloche d'urgence</button>
		<button>Téléphone régulier</button>
		<button>Fin</button>
	</div>
</div>
<script src="Main.js"></script>
<script src="Context.js"></script>
<script src="DayState.js"></script>
<script src="NightState.js"></script>
</body>
</html>

style.css


/****************************************************************
partie commune
****************************************************************/
/*reset*/
body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, form, 
fieldset, input, textarea, p, blockquote, th, td{
    margin: 0;
    padding: 0;
}
html{
}
h1, h2, h3, h4, h5, h6{
    font-size: 100%;
    font-weight: normal;
}
ol, ul{
    list-style:none;
}
fieldset, img{
    border:0;
}
table{
    border-collapse: collapse;
    border-spacing:0;
}
caption, th{
    text-align: left;
}
address, caption, cite, code, dfn, em, strong, th, var{
    font-style: normal;
    font-weight: normal;
}
img {
   vertical-align: bottom;
}
html {
    font-size: 10px;
    font-size: 62.5%;
}
a {
    color: #000;
    text-decoration: none;
}
/*setting*/
body {
    font-size: 10px;
    font-size: 1rem;
    background-color: #dbdbdb;
}
.container {
    width: 490px;
    margin: 0 auto;
}
.flex {
    display: flex;
    justify-content: space-between;
    align-items: center;
}
/*main*/
.main {
	margin-top: 20px;
	flex-direction: column;
}
.main input {
	width: 100%;
	height: 25px;
	border: 1px solid #000;
	box-sizing: border-box;
}
.main textarea {
	width: 100%;
	height: 200px;
	box-sizing: border-box;
	border: 1px solid #000;
	border-top: 0;
    overflow: scroll;
}
.main textarea:focus {
	outline: 0;
	
}
.main .button_area {
	width: 100%;
	border:1px solid #000;
	border-top: 0;
	justify-content: center;
	box-sizing: border-box;
}
.button_area button {
	margin: 5px;
}

Main.js


MAIN = {};
MAIN.context;
MAIN.timer;
MAIN.hour;

MAIN.init = function() {
    MAIN.context = new Context();
    MAIN.hour = 0;
    MAIN.timer = setInterval(MAIN.mainLoop, 500);
};
MAIN.mainLoop = function() {
    MAIN.context.setClock(MAIN.hour);
    MAIN.hour += 1;
    if (MAIN.hour === 25) {
        MAIN.hour = 0;
    }
};

window.addEventListener("load", MAIN.init);

Context.js


var Context = function() {
    this.state = DAY_STATE.dayState.getInstance();
    this.textFieldElm = document.querySelector(".main input[type='text']");
    this.textAreaElm = document.querySelector(".main textarea");

    document.querySelectorAll(".main .button_area button").forEach(function(b) {
        switch (b.innerText) {
            case "Utilisation sûre":
                b.addEventListener("click", function() {
                    MAIN.context.state.doUse(MAIN.context);
                });
                break;
            case "cloche d'urgence":
                b.addEventListener("click", function() {
                    MAIN.context.state.doAlarm(MAIN.context);
                });
                break;
            case "Téléphone régulier":
                b.addEventListener("click", function() {
                    MAIN.context.state.doPhone(MAIN.context);
                });
                break;
            case "Fin":
                b.addEventListener("click", function() {
                    window.close();
                });
                break;
        }
    });
};

Context.prototype = {
    constructor: Context,

    setClock: function(hour) {
        var clockString = "L'heure actuelle est";

        if (hour < 10) {
            clockString += "0" + hour + ":00";
        } else {
            clockString += hour + ":00";
        }
        console.log(clockString);
        this.textFieldElm.value = clockString;
        this.state.doClock(this, hour);

    },
    changeState: function(state) {
        console.log(this.state.getName() + "À partir de k" + state.getName() + "L'état a changé.");
        this.state = state;
    },
    callSecurityCenter: function(msg) {
        this.textAreaElm.value += msg + "\n";
        this.textAreaElm.scrollTop = this.textAreaElm.scrollHeight;
    },
    recordLog: function(msg) {
        this.textAreaElm.value += msg + "\n";
        this.textAreaElm.scrollTop = this.textAreaElm.scrollHeight;
    }
};

DayState.js


DAY_STATE = {};
DAY_STATE.dayState = (function() {
    var singleton;
    var name;

    var init = function() {
        name = "[Jour]"
        return {
            doClock: function(context, hour) {
                if (hour < 9 || 17 <= hour) {
                    context.changeState(NIGHT_STATE.nightState.getInstance());
                }
            },
            doUse: function(context) {
                context.recordLog("Utilisation sûre(Jour)");
            },
            doAlarm: function(context) {
                context.callSecurityCenter("cloche d'urgence(Jour)");
            },
            doPhone(context) {
                context.callSecurityCenter("Appel normal(Jour)");
            },
            getName: function() {
                return name;
            }
        };
    };

    return {
        getInstance: function() {
            if (!singleton) {
                singleton = init();
            }

            return singleton;
        }
    }
})();

NightState.js


NIGHT_STATE = {};
NIGHT_STATE.nightState = (function() {
    var singleton;
    var name;

    var init = function() {
        name = "[Nuit]";
        return {
            doClock: function(context, hour) {
                if (9 <= hour && hour < 17) {
                    context.changeState(DAY_STATE.dayState.getInstance());
                }
            },
            doUse: function(context) {
                context.recordLog("Urgence: utilisez le coffre-fort la nuit!")
            },
            doAlarm: function(context) {
                context.callSecurityCenter("cloche d'urgence(Nuit)");
            },
            doPhone: function(context) {
                context.callSecurityCenter("Enregistrement des appels de nuit");
            },
            getName: function() {
                return name;
            }
        };
    };

    return {
        getInstance: function() {
            if (!singleton) {
                singleton = init();
            }

            return singleton;
        }
    };
})();

Caractères dans le modèle État

** Rôle de l'État **

Représente l'état Une collection de méthodes qui se comportent de manière dépendante de l'état Exemple de programme ⇒ État (interface)

** Le rôle de Concreate State **

Représenter des états individuels spécifiques Exemple de programme ⇒ DayState (classe), NightState (classe)

** Le rôle du contexte (situation, contexte, contexte) **

Représente l'état actuel Exemple de programme ⇒ Contexte (interface)

Diagramme de classe de modèle d'état

State2.png

Besoin d'un modèle d'état

Vous pouvez également changer le mouvement en voyant le changement d'état avec l'instruction if ou l'instruction switch

Sample.java


public void method1(Statut) {
  if (État A) {
    System.out.println("Depuis l'état un bonjour");
  }
  if (État B) {
    System.out.println("Bonsoir car il est en état B");
  }
}

public void method2(Statut) {
  if (État A) {
    System.out.println("Bonjour car il est dans l'état A");
  }
  if (État B) {
    System.out.println("Bonsoir car il est en état B");
  }
}

Mais le programmeur doit être conscient de la différence d'état à chaque fois. De nombreux endroits doivent être modifiés lors de l'ajout d'états Si l'état est exprimé sous forme de classe, le "changement d'état" peut être exprimé en changeant de classe.

qiita1.PNG

Facile à comprendre car il suffit d'ajouter le rôle ConcreateState lors de l'ajout d'un nouvel état

qiita2.PNG

Lors de l'utilisation du modèle State

Modèles associés

référence

[Introduction aux modèles de conception appris dans le langage Java augmenté et révisé](https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82% E7% 89% 88Java% E8% A8% 80% E8% AA% 9E% E3% 81% A7% E5% AD% A6% E3% 81% B6% E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3% 83% B3% E5% 85% A5% E9% 96% 80-% E7% B5 % 90% E5% 9F% 8E-% E6% B5% A9 / dp / 4797327030)

Recommended Posts

Comprendre le modèle d'état en comparant le code JavaScript et Java
Comprendre le modèle Decorator en comparant le code JavaScript et Java
Comprendre le modèle composite en comparant le code JavaScript et Java
Comprendre les modèles de conception en comparant les implémentations en JavaScript et Java [mis à jour de temps en temps]
Exécution par sous-shell (et mise à jour des variables)
Notifier l'erreur et la fin de l'exécution par LINE [Python]
exécution et erreur de pytube
Comprendre le modèle Decorator en comparant le code JavaScript et Java
Comprendre le modèle d'état en comparant le code JavaScript et Java
Comprendre le modèle composite en comparant le code JavaScript et Java
Différence entre le processus de premier plan et le processus d'arrière-plan compris par principe
Essayer d'implémenter et de comprendre les arborescences de segments étape par étape (python)
Lisez le fichier en spécifiant le code de caractère.
Comprendre l'arbre de décision et classer les documents
Apprenez le modèle de conception "État" en Python
Comprendre le modèle Decorator en comparant le code JavaScript et Java
Comprendre le modèle d'état en comparant le code JavaScript et Java
Comprendre le modèle composite en comparant le code JavaScript et Java
Comprendre les modèles de conception en comparant les implémentations en JavaScript et Java [mis à jour de temps en temps]
Essayer d'implémenter et de comprendre les arborescences de segments étape par étape (python)
Compilation et exécution Java comprises par CLI
Lisez le fichier en spécifiant le code de caractère.
Comprendre l'arbre de décision et classer les documents
Apprenez le modèle de conception «Stratégie» avec Python