[JAVA] J'ai utilisé le modèle Mediator pour exprimer un puzzle de traversée de rivière.

Le dernier à temps plein est un oncle d'amélioration des opérations. Je réétudie les modèles de conception.

Pour mieux comprendre le modèle Mediator Comme exemple de code, je pense que c'est la Nième décoction ... J'ai utilisé le puzzle de la traversée de la rivière comme code.

Ce n'est pas un programme qui trouve la réponse au puzzle de la traversée de la rivière C'est un programme qui simule un puzzle de traversée de rivière.

Si vous faites une erreur en reconnaissant Mediator, Si vous le souhaitez, je vous serais reconnaissant si vous pouviez le signaler.

environnement

Puzzle de traversée de rivière

C'est le fameux. De ce rivage, vous pouvez utiliser un bateau pour traverser vers l'autre rivage.

Je pense qu'il y a différents personnages qui apparaissent, Cette fois, j'ai choisi des fermiers, des loups, des chèvres et du chou.

Seuls les agriculteurs peuvent ramer un bateau. Seuls le fermier et un autre personnage peuvent monter à bord du navire. Si un loup ou une chèvre est abandonné alors qu'il n'y a pas de fermier sur le même rivage, le loup mangera la chèvre. Si vous laissez des chèvres et du chou alors qu'il n'y a pas d'agriculteur sur la même rive, les chèvres mangeront le chou.

Comment puis-je traverser en toute sécurité de l'autre côté de la rivière? C'est.

supposition

Farmer.java, Chabbage.java, Goat.java, Wolf.java, Il hérite des éléments suivants:

CharacterBase.java


public abstract class CharacterBase implements Character {
    private Position position;
    private Status status;

    public CharacterBase() {
        this.position = Position.FRONT;
        this.status = Status.ALIVE;
    }

    @Override
    public Status getStatus() {
        return this.status;
    }

    @Override
    public void setStatus(Status status) {
        this.status = status;
    }

    @Override
    public Position getPosition() {
        return this.position;
    }

    @Override
    public void setPosition(Position position) {
        this.position = position;
    }

    @Override
    public void cross() {
        switch (this.getPosition()) {
        case FRONT:
            this.setPosition(Position.BEYOND);

            break;

        case BEYOND:
            this.setPosition(Position.FRONT);

            break;

        default:
            break;
        }
    }

}

Aussi, Farmer.java uniquement, Implémente la méthode cross (Character with Character).

Farmer.java


public class Farmer extends CharacterBase {
    public void cross(Character withCharacter) {
        if (withCharacter == null) {
            throw new IllegalArgumentException("Veuillez spécifier le caractère avec lequel croiser.");
        }

        if (withCharacter instanceof Farmer) {
            throw new IllegalArgumentException("Vous ne pouvez pas spécifier d'agriculteur.");
        }

        if (!this.getPosition().equals(withCharacter.getPosition())) {
            throw new IllegalArgumentException("Seuls les personnages dans la même position peuvent se croiser.");

        }

        this.cross();
        withCharacter.cross();
    }
}

Sans médiateur

Parce qu'il n'y a pas de classe qui connaisse tous les personnages Vérifiez l'état un par un dans la classe d'exécution, Je dois mettre à jour les statistiques de mon personnage.

CrossRiverExecutor.java



public class CrossRiverExecutor {
    private Farmer farmer;
    private Wolf wolf;
    private Goat goat;
    private Cabbage cabbage;

    public CrossRiverExecutor(Farmer farmer, Wolf wolf, Goat goat, Cabbage cabbage) {
        this.farmer = farmer;
        this.wolf = wolf;
        this.goat = goat;
        this.cabbage = cabbage;
    }

    public void execute() {
        farmer.cross(goat);
        //Ce rivage: loup, chou
        //L'autre côté: fermier, chèvre
        updateStatus();

        farmer.cross();
        //Ce rivage: fermier, loup, chou
        //L'autre côté: la chèvre
        updateStatus();

        farmer.cross(cabbage);
        //Ce rivage: le loup
        //L'autre côté: fermier, chèvre, chou
        updateStatus();

        farmer.cross(goat);
        //Ce rivage: fermier, chèvre, loup
        //L'autre côté: le chou
        updateStatus();

        farmer.cross(wolf);
        //Ce rivage: la chèvre
        //L'autre côté: fermier, loup, chou
        updateStatus();

        farmer.cross();
        //Ce rivage: fermier, chèvre
        //L'autre côté: loup, chou
        updateStatus();

        farmer.cross(goat);
        //Ce rivage:
        //L'autre côté: agriculteurs, loups, chèvres, choux
        updateStatus();
    }


    private void updateStatus() {
        if (!farmer.getPosition().equals(goat.getPosition()) && wolf.getPosition().equals(goat.getPosition())) {
            goat.setStatus(Status.DEAD);
        }

        if (!farmer.getPosition().equals(cabbage.getPosition()) && cabbage.getPosition().equals(goat.getPosition())) {
            cabbage.setStatus(Status.DEAD);
        }
    }
}


Je pense que vous pouvez encore exprimer le puzzle de la traversée de la rivière, C'est difficile à lire et il est difficile de tester la méthode updateStatus. Je ne pense pas que le code soit en très bon état.

Si vous avez un médiateur

Ici, préparez Mediator à connaître tout le personnage.

CrossRiverMediator.java



public class CrossRiverMediator implements CrossRiver {
    private Farmer farmer;
    private Wolf wolf;
    private Goat goat;
    private Cabbage cabbage;

    public CrossRiverMediator(Farmer farmer, Wolf wolf, Goat goat, Cabbage cabbage) {
        this.farmer = farmer;
        this.wolf = wolf;
        this.goat = goat;
        this.cabbage = cabbage;
    }

    @Override
    public void cross(Character character) {

        switch (character.getPosition()) {
        case FRONT:
            character.setPosition(Position.BEYOND);

            break;

        case BEYOND:
            character.setPosition(Position.FRONT);

            break;

        default:
            break;
        }
    }

    @Override
    public void cross(Farmer character, Character withCharacter) {
        if (withCharacter == null) {
            throw new IllegalArgumentException("Veuillez spécifier le caractère avec lequel croiser.");
        }

        if (withCharacter instanceof Farmer) {
            throw new IllegalArgumentException("Vous ne pouvez pas spécifier d'agriculteur.");
        }

        if (!character.getPosition().equals(withCharacter.getPosition())) {
            throw new IllegalArgumentException("Seuls les personnages dans la même position peuvent se croiser.");

        }

        character.cross();
        withCharacter.cross();
        updateStatus();
    }

    private void updateStatus() {
        if (!farmer.getPosition().equals(goat.getPosition()) && wolf.getPosition().equals(goat.getPosition())) {
            goat.setStatus(Status.DEAD);
        }

        if (!farmer.getPosition().equals(cabbage.getPosition()) && cabbage.getPosition().equals(goat.getPosition())) {
            cabbage.setStatus(Status.DEAD);
        }

    }
}


Parce que je connais tous les personnages Vous pouvez exécuter la méthode updateStatus pour mettre à jour la vie et la mort de chaque personnage.

Aussi, avec ça CharacterBase.java, la classe parente de chaque caractère, La méthode cross () et la méthode cross (Character) de Farmer.java, Modifiez-le pour qu'il s'exécute via Mediator.

CharacterBase.java



public abstract class CharacterBase implements Character {
    protected CrossRiver crossRiver;
    private Position position;
    private Status status;

    public CharacterBase() {
        this.position = Position.FRONT;
        this.status = Status.ALIVE;
    }

    @Override
    public void setMediator(CrossRiver crossRiver) {
        this.crossRiver = crossRiver;
    }

    @Override
    public Status getStatus() {
        return this.status;
    }

    @Override
    public void setStatus(Status status) {
        this.status = status;
    }

    @Override
    public Position getPosition() {
        return this.position;
    }

    @Override
    public void setPosition(Position position) {
        this.position = position;
    }

    @Override
    public void cross() {
        this.crossRiver.cross(this);
    }
}

Farmer.java



public class Farmer extends CharacterBase {
    public void cross(Character withCharacter) {
        this.crossRiver.cross(this, withCharacter);
    }
}

Ensuite, la classe d'exécution Ce sera comme suit.

CrossRiverExecutor.java



public class CrossRiverExecutor {
    private Farmer farmer;
    private Wolf wolf;
    private Goat goat;
    private Cabbage cabbage;
    private CrossRiverMediator crossRiver;

    public CrossRiverExecutor() {
        farmer = new Farmer();
        wolf = new Wolf();
        goat = new Goat();
        cabbage = new Cabbage();

        crossRiver = new CrossRiverMediator(farmer, wolf, goat, cabbage);
        farmer.setMediator(crossRiver);
        wolf.setMediator(crossRiver);
        goat.setMediator(crossRiver);
        cabbage.setMediator(crossRiver);
    }

    public void execute() {
        farmer.cross(goat);     //Ce rivage: loup, chou L'autre rivage: fermier, chèvre
        farmer.cross();         //Cette rive: fermier, loup, chou L'autre rive: chèvre
        farmer.cross(cabbage);  //Cette rive: le loup L'autre rive: fermier, chèvre, chou
        farmer.cross(goat);     //Cette rive: fermier, chèvre, loup Autre rive: chou
        farmer.cross(wolf);     //Ce rivage: Chèvre L'autre rivage: fermier, loup, chou
        farmer.cross();         //Cette rive: fermier, chèvre L'autre rive: loup, chou
        farmer.cross(goat);     //Ce rivage: L'autre rivage: agriculteurs, loups, chèvres, choux
    }
}

Par conséquent, la logique peut être séparée de la classe d'exécution, Lors du test de la logique, il vous suffit de tester le Mediator, Je pense que c'est un code relativement bon.

résultat

J'ai pu programmer un puzzle de traversée de rivière. https://github.com/naokiur/design-pattern-sample/tree/master/src/main/java/jp/ne/naokiur/design/pattern/mediator

Je l'ai utilisé comme référence

https://github.com/iluwatar/java-design-patterns http://language-and-engineering.hatenablog.jp/entry/20120330/p1

Recommended Posts

J'ai utilisé le modèle Mediator pour exprimer un puzzle de traversée de rivière.
J'ai essayé de résumer les méthodes utilisées
J'ai essayé d'implémenter le modèle Iterator
Code utilisé pour connecter Rails 3 à PostgreSQL 10
Je souhaite ajouter une fonction de suppression à la fonction de commentaire
Je veux appeler une méthode et compter le nombre
Je veux donner un nom de classe à l'attribut select
J'ai essayé d'exprimer les résultats avant et après de la classe Date avec une ligne droite numérique
J'ai essayé d'illuminer le sapin de Noël dans un jeu de la vie
J'ai fait un petit bijou pour poster le texte du mode org sur qiita
[Java] J'ai essayé de faire un labyrinthe par la méthode de creusage ♪
J'ai créé un outil pour afficher la différence du fichier CSV
J'ai essayé d'expliquer la méthode
L'histoire que je voulais développer Zip
[Rails] J'ai découvert les fichiers de migration! (Ajout d'une colonne au tableau)
Une histoire à laquelle j'étais accro lors du test de l'API à l'aide de MockMVC
Je ne peux pas construire si je définis la destination de construction sur un simulateur avec XCode12!
C'était une vie que je voulais réinitialiser le compteur associatif thread-safe
J'ai utilisé Docker pour solidifier le modèle à développer avec Spring Boot.