2016-10-17 2 views
4

Je suis en train de concevoir un système de commande et le modèle de conception d'état semble approprié parce que la commande peut changer son état et ainsi les fonctionnalités permises pour la commande. Ci-dessous mon diagramme de classes de base:Modèle de conception d'état conforme à Liskov

Je n'aime pas cette approche parce que les clients ne peuvent pas voir si une méthode est prise en charge et viole le principe Liskov. J'ai créé une alternative ci-dessous:

J'aime mieux, mais toujours le client doit vérifier si une méthode est prise en charge. Mais ils peuvent toujours appeler la méthode non supportée et obtenir une exception. Est-ce que cela viole encore le principe de Liskov?

Y a-t-il une meilleure conception qui soit conforme à Liskov et empêche l'utilisateur d'appeler des méthodes invalides pour un état spécifique?

+0

Je ne comprends pas ce que vous entendez par « ne peut pas voir si une méthode est prise en charge ». Les OrderStates concrets vont tous implémenter les méthodes OrderState. Juste certains d'entre eux lèveront une exception quand l'état n'autorise pas l'opération actuellement. Cela ne viole pas LSP imo. En outre, je ne vois pas en quoi cela est différent lorsque, au lieu de déclencher directement un UnsupportedOpEx, vous appelez d'abord l'une des méthodes can *, puis l'augmentez. Imo, permettant aux consommateurs de l'Ordre d'appeler les méthodes can * est pire, car il déplace la responsabilité en dehors de l'objet Order. – Gordon

+0

Dans le diagramme de classe 1, le client ne peut pas détecter si une opération est valide pour un état spécifique. Ensuite, il n'y a aucun moyen de savoir si un bouton de paiement ou un bouton d'annulation devrait être affiché pour. Dans ma compréhension de LSP lancer une exception notSupportedException est une façon commune de briser le LSP. Cela parce que le sous-type ne fait pas ce qui est dit, donc le sous-type ne peut pas être substituable à son type de base. –

+0

Concrete 'OrderStates' implémentera tous l'interface' OrderState' et donc ses méthodes. Toutes ces méthodes peuvent - par contrat d'interface si possible - potentiellement déclencher une exception. Vous pouvez donc remplacer n'importe quel sous-type concret de OrderState par un autre. Par conséquent, vous ne violez pas le principe de substitution de Liskov. Vous pouvez utiliser le même modèle pour dessiner les boutons btw. Passez simplement un rendu de bouton à OrderState et demandez-lui de renvoyer le bon bouton à partir de OrderState concret, par ex. Confirmé dira le ButtonRenderer de rendre un bouton Pay, etc. – Gordon

Répondre

0

Ce que vous montrez n'est pas un modèle d'état. Le modèle d'état modifie le comportement de l'objet lorsque son état interne change. Par exemple, un interrupteur d'éclairage peut allumer ou éteindre la lumière lorsque vous la basculez, en fonction de son état (comportement différent sur la même méthode).

Avec cette interface de commande (4 méthodes diff), je ne vois aucun avantage à introduire un modèle d'état. Cela ne fera que compliquer les choses sans raison. Mais je ne connais pas tous les détails, donc c'est à vous de décider quoi faire ensuite.

Vérifiez ce lien pour voir des exemples de mise en œuvre de patten Etat https://sourcemaking.com/design_patterns/state

+0

La raison pour laquelle j'utilise le modèle d'état dans le design est parce que l'ordre change d'état et cela change son comportement. Si je crée des classes d'ordre Seperator alors l'ordre ne peut pas changer son comportement ar runtime. Avez-vous une suggestion pour un modèle différent? –

+0

La solution la plus simple est un seul modèle de commande avec 4 méthodes diff qui lèvent une exception lorsque vous essayez d'utiliser une méthode lorsque l'objet est dans un état inapproprié. Habituellement, quand je ne connais pas tous les détails, je vais avec la solution la plus simple qui sera plus facile à refactoriser plus tard. Mais tout dépend de l'utilisation de la commande dans votre application/code. Par exemple, si vous possédez une interface Order avec une méthode 'proceedToTheNextState', vous pouvez créer 4 états: Confirmer, Annuler, Payer, Expédier et effectuer tous les travaux liés à l'état et passer à l'état suivant. –

+0

En outre, il peut y avoir plusieurs raisons différentes pour lesquelles vous souhaiterez peut-être diviser la logique du comportement de l'ordre. Et la solution résultante pourrait ne pas être la mise en œuvre exacte du modèle d'état. Tout va bien si tout est fait pour une raison. Vous ne pouvez pas rompre LSP si vous suivez vos interfaces et définitions de méthodes dans les sous-classes. –