Imaginez que j'ai une classe qui représente une simple machine à laver. Il peut effectuer des opérations suivantes dans l'ordre suivant: Activer -> Lavage -> Centrifuge -> Éteindre Strong>. Je vois deux alternatives de base: p>
Je peux avoir une classe de lavage de la classe avec des méthodes Je peux laisser la classe elle-même s'occuper des transitions correctes et avoir la méthode unique Quelle alternative est meilleure? Ou peut-être qu'il y a d'autres alternatives, de meilleures alternatives que j'ai manquées de décrire? p>
10 Réponses :
Le premier est exactement ce que je ferais. laver code> et
Centrifuge code> vérifierait le drapeau qui suit si la machine est allumée et lancez une exception si ce n'est pas le cas, mais il n'y a pas d'ordre d'exploitation obligatoire; Vous pouvez appeler
Centrifuge code> avant
WASH code> si vous avez vraiment senti le besoin p>
erm, un peu bizarre mais voilà; P>
Je regarderais même des délégués. Donc, pour un type de cycle de lavage particulier, un soulèvement, une lumière, des Studdsy, économique, etc. J'aurais une interface pour chacun. P>
Puis, avec l'utilisation de génériques, je créerais le type de lavage approprié que je veux. P>
Le type de lavage aurait alors un événement de lavage qui déléguette, dans l'ordre, les cycles à exécuter. P>
Je pense que Turnon () Strong>, Wash () strong>, centerfuge () strong> etc. devrait être des méthodes privées / protégées. L'interface publique doit être
La machine à laver doit savoir comment exécuter correctement une charge. Peut-être avant de laver une charge, certains éléments de configuration devraient être définis (avec des valeurs par défaut, si non défini), comme quel type de charge (lumières vs sombre) ou taille (petit, moyen, grand). L'utilisateur (une autre classe) doit savoir comment configurer correctement une charge à exécuter, mais pour laver une charge, le lave-linge doit seulement expirer une méthode, quelque chose comme Alternativement, vous pouvez toujours exposer les fonctions publiques pour transformer la laveuse sur et éteindre, puis si washload code>. En interne, il gérerait ce qui doit être appelé quand laver une charge de blanchisserie. P>
washload code> a été appelé lorsque la rondelle était éteinte, il serait approprié de jeter une exception. En outre, dans ce scénario, je ferais probablement les paramètres de la laveuse définie via une méthode unique
setOchartOPtions code> qui prendrait une autre classe, ce serait quelque chose comme
loadoptions code> et défini toutes les caractéristiques vous vouliez configurable. Je voudrais également jeter une exception si la laveuse n'était pas allumée. P>
J'aurais un "Code" de haut niveau ' établir un diagramme de transition d'état de tous les états dont vous avez besoin, y compris (pour chaque état ) p>
Vous pouvez ou non besoin de conditions d'entrée / de sortie (par exemple, vous pouvez forcer les conditions avec une action d'entrée / sortie dans certains cas). Pour des raisons de sécurité, certaines conditions peuvent être bonnes (par exemple sortant d'un état de «veille» ou d'une entrée dans un état «dangereux» comme Spin Sèche) P>
Vous créez également Encore une fois, vous n'avez peut-être pas besoin de tous, et de nombreuses transitions n'auront que les états «de» et «à» spécifiés. P>
Dans les deux cas, essayez de conserver chaque Il devrait être assez évident à ce stade que vous pouvez créer une classe code> d'état code> assez générique qui inclut des fonctions abstraites / surchargées pour toutes ces choses, et également pour la transition Si vous le faites particulièrement génériques, les Vous pouvez ensuite demander des transitions, soit à partir de dans les états em> (c'est-à-dire qu'un état particulier peut savoir quand il est terminé, et sachez quel état passer à la suivante) ou vous pourriez avoir une classe externe qui contrôle Les transitions de l'état (chaque état est alors très simple, de manière purement prise en charge de ses propres actions, et la classe externe décide de la commande et du calendrier des transitions). P>
Dans mon expérience avec ces choses, il est judicieux de séparer la logique de haut niveau d'ordre / chronométrage délibéré de chaque action et de la logique de réaction de faible niveau à certains événements matériels (par exemple, la transition de l'état "remplissage" lorsque Le niveau d'eau est atteint). P>
C'est un design vraiment générique cependant, et vous pouvez obtenir exactement la même fonctionnalité un tas de différentes manières - il y a rarement un simple em> droite em> moyen de faire les choses .. . p> Machine d'état Code> qui contrôle l'entrée / la sortie / sortie de chaque état (où les états pourraient être des choses comme "remplissage", "lavage", "Rinçage", " ',' Vider ',' Spin Sèche ', etc.) P>
transitions code>, qui définissent les liens entre les états. Une transition a p>
état code> et
transition code> aussi simple que celui que a besoin em> être (essayer de mettre les conditions / actions Là où ils ont le plus de sens, il y a évidemment un double potentiel de ceux-ci à définir dans un
état code> et em> a
transition code> en raison de la conception générique ) p>
code > classe. La classe d'état code> code> peut appeler chacune de ces fonctions de membre selon les besoins, en fonction des transitions demandées. P>
états code> et
transitions code> peuvent être enregistrés avec la machine d'état code> au temps de construction, ou vous pourriez Il suffit de coder la machine d'état code> pour les contenir tous. P>
Je pense que c'est une bonne réponse! J'ajouterais que je trouve utile de penser à l'interface utilisateur courante dans un fil et la machine à laver états / transitions / travaux fonctionnant dans un autre. En outre, on pourrait utiliser vos états comme des nœuds et transitions comme des bords (plutôt que d'avoir la transition de la transition «de» et de «à» état) dans une structure graphique. Cela permettrait aux choses comme énumérer les états «à» pour un nœud donné. J'aime utiliser Jung pour les structures graphiques.
Oui, les nœuds / bords sont fondamentalement la même idée, comme je l'ai dit que la conception est assez générique, de sorte que les transitions ont «de» et «à» états, ou si des États ont une liste de transitions disponibles n'est pas trop importante, il y a un beaucoup de moyens ceux-ci peuvent être mis en œuvre
sur ma machine à laver, vous avez accès à deux boutons. Je suis un peu confus quant à ce que les limitations sont dans votre cas.
lorsque vous "activez" un cycle (en tournant le bouton), la machine commencera à fonctionner si vous le tournez au milieu ou au début d'un cycle. P>
Voici un vraiment , Exemple vraiment de base de la façon dont je vais traduire cela en une classe: p>
Dernièrement, je vais fonctionnel strong> et en utilisant des objets immuables avec Martin Fowler / JQuery enchaînant fluent style fort>. code: p>
Bien que ce soit bien, cela ne modifie pas vraiment le comportement réel d'une machine à laver. L'utilisateur (sur la plupart des modèles) ne peut généralement pas choisir la commande et la longueur des états, bien qu'ils puissent généralement choisir entre plusieurs modèles de cycle. Bien que je suppose que votre Examplerun pourrait être un modèle de cycle choisi.
@MYSTERE Man Le point est que les états sont des objets immuables et seuls les états savent quel est l'état suivant. Je suis à peu près sûr pour une rondelle que vous pourriez obtenir cela pour travailler.
rien contre le motif et le code, ça a vraiment l'air bien! Et l'OP a demandé une solution pour une simple machine à états. Juste pour le monde réel - Les machines modernes varient du programme, par exemple sur la base de la mesure de la qualité de l'eau usée - comme: si elle est sale, lavez à nouveau. Cela introduirait des conditions et des succursales.
La plupart des machines à laver les plus occidentales utilisent une minuterie pour passer du cycle au cycle. Cette minuterie peut être considérée comme une machine d'état. Cependant, il est important de réaliser qu'une machine d'incendie se déroule, pas l'utilisateur. L'utilisateur définit le mode initial, puis sur son entreprise. P>
Si de manière interne, vous pouvez avoir des fonctions de lavage, de rinçage, de spin, l'interface réelle serait la création () et le début () et l'arrêt (). Vous pouvez également avoir des propriétés supplémentaires, telles que le niveau d'eau, la vitesse d'agitation, la température de l'eau, etc. p>
Démarrage provoque le temps d'avancer, lequel après une période de temps entre dans l'état suivant, jusqu'à ce qu'il soit finalement complet. p>
L'option A est comme une laveuse manuelle tandis que l'option B est comme une laveuse automatique. Les deux options sont utiles à leurs utilisateurs ciblant: P>
Un utilisateur d'option A peut profiter de la programmation manuelle de l'ensemble du processus (comme doubler le cercle de lavage ou enseigner le petit que si vous éteignez la machine pendant que c'est dans le cercle de centrifugation). P>
Un utilisateur d'option B peut profiter de la simplicité et écrire une série de séries factices - apprendre à votre auto lavage en 21 secondes: -) p>
Chaque machine à laver a un contrôleur strong> et un programme Dans les deux cas, la machine a des sous-systèmes supplémentaires et le contrôleur notifie strong> les sous-systèmes pour effectuer une action, comme verrouiller la porte em>, Eau thermique jusqu'à 40 ° C em> ou tourner le tambour em>. P>
Le contrôleur lui-même connaît la séquence, qui est jolie linéaire et la minuterie basée sur des machines anciennes ou complexes pour les systèmes modernes qui varient en fonction de la séquence des données du capteur. Mais dans les deux cas, il exécute une série de commandes pouvant notifier des capteurs et des acteurs. P>
Si vous regardez le système de lavage de ce point de vue, vous pouvez utiliser la commande
"Imaginez que vous mettez en œuvre l'événement de clic du bouton de centrifuge." Pourquoi l'utilisateur déciderait-il jamais ce qui se passe avec la centrifugeuse? Je ne dis certainement jamais à ma machine à laver comment faire ses affaires ...
@ harschaware Imagine que ce capteur de niveau d'eau envoie un signal "chargé" ou cet utilisateur appuie sur le bouton "Ouvrir la porte" à tout moment de fonctionnement.
Oui, mais un utilisateur ne ferait pas tourner la centrifugeuse. L'utilisateur peut se tourner vers le cycle d'essorage et exécuter, à quel point la machine d'état déciderait s'il s'agit d'une demande valide pour l'état donné. La centrifugeuse est une opération mécanique utilisée par le FSM et le cycle de rotation serait une entrée de l'utilisateur.