使用观察者模式在地图上移动圆圈

时间:2017-11-25 13:30:22

标签: java design-patterns geometry observer-pattern observers

我的java程序有一个(可能很简单)问题。我正在尝试创建一个从一个地方移动到另一个地方的圆圈。地图是一个简单的对话游戏的一部分,说“去这里”,地图应该对它作出反应。它必须使用Observer设计模式。

到目前为止,我已经在游戏中实现了地图,但我无法理解如何使圆圈功能正常,同时也使用Observer。谢谢你的帮助

package GUI;

import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import logika.Game;
import logika.IGame;
import main.Main;
import utils.Observer;


public class Mapa extends AnchorPane implements Observer{

    private IGame game;
    private Circle dot;
    //private double posTop = 0.0;
    //private double posLeft = 0.0;

    public Mapa(IGame game){
            this.game = game;
            game.getGamePlan().registerObserver(this);
            init();
    }

    private void init(){

        ImageView obrazekImageView = new ImageView(new Image(Main.class.getResourceAsStream("/zdroje/mapa.gif"),255,255,false,true));

        tecka = new Circle(10, Paint.valueOf("red"));

       //this.setTopAnchor(tecka, 15.0);
       //this.setLeftAnchor(tecka, 20.0);

        this.getChildren().addAll(obrazekImageView, dot);
        update();
    }

    public void newGame(IGame newGame){
        game.getGamePlan().removeObserver(this);
        game= newGame;
        game.getGamePlan().registerObserver(this);
        update();

    }

    @Override
    public void update(){
        this.setTopAnchor(this, game.getGamePlan().getCurrentPlace().getPosTop());
        this.setLeftAnchor(this, game.getGamePlan().getCurrentPlace().getPosLeft());
    }
}

1 个答案:

答案 0 :(得分:0)

你应该实现像维基百科的这个UML图中所见的模式:

enter image description here

那就是像CommandObserver这样的接口,每次发生事件时都会在每个观察者上调用notify之类的方法。该事件包含完整的命令以及移动圆圈所需的所有内容。我假设您可以通过仅引用圆圈来移动它。总而言之,它可能看起来像

public interface CommandObserver {
    void notify(String command, Circle circle);
}

接下来,事件的调用者(我们称之为CommandReceiver)必须有一些register方法,所有观察者都可以注册。如果事件发生,它必须具有某种notifyObservers

public class CommandReceiver {
    // The reference to the circle
    private Circle circle = ...

    private Set<CommandObserver> observers = new HashSet<>();

    public void registerObserver(CommandObserver observer) {
        observers.add(observer);
    }

    public void unregisterObserver(CommandObserver observer) {
        observers.remove(observer);
    }

    private void notifyObserver(String command, Circle circle) {
        for (CommandObserver observer : observers) {
            observer.notify(command, circle);
        }
    }

    // If a command was entered
    public void commandEntered(String command) {
        notifyObserver(command, circle);
    }
}

最后,您将为所有可能的命令实现观察者:

public PositionMoveObserver implements CommandObserver {
    private int x;
    private int y;
    private String command;

    public PositionMoveObserver(int x, int y, String command) {
        this.x = x;
        this.y = y;
        this.command = command;
    }

    @Override
    public void notify(String command, Circle circle) {
        // Not interested in, reject
        if (!this.command.equals(command)) {
            return;
        }

        // Move the circle to our destination
        circle.moveTo(x, y);
    }
}

然后为每个位置创建并注册它:

private void createObservers(CommandReceiver invoker) {
    invoker.registerObserver(new PositionMoveObserver(0, 5, "bottomLeft"));
    invoker.registerObserver(new PositionMoveObserver(100, 5, "bottomRight"));
    invoker.registerObserver(new PositionMoveObserver(0, 50, "middleLeft"));
    ...
}

请注意,对于特定命令,只有一个观察者应该监听它,否则多个实例会移动圆圈,结果将取决于调用者HashSet的迭代顺序。