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?
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
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. –
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