简体   繁体   English

MVP中的观察者模式

[英]Observer Pattern in MVP

I have a System (game) which I try to implement using the architecture Model-View-Presenter. 我有一个系统(游戏),尝试使用体系结构Model-View-Presenter实现。 What I have done right now is a while loop in the presenter that calls continuously the view methods for displaying. 我现在所做的是在演示者中的一个while循环,该循环不断调用用于显示的view方法。 The way I do this is using a Producer/Consumer pattern, where the View register and event handler for touch events(Android) and produce the corresponding touch imstances, that the presenter consumes in the while loop. 我这样做的方式是使用Producer / Consumer模式,其中View寄存器和触摸事件的事件处理程序(Android)并产生相应的触摸实例,供演示者在while循环中使用。

Now I would like to use the pattern Observer/Suscriber between The Model and the Presenter. 现在,我想在The Model和Presenter之间使用模式Observer / Suscriber。 Using this the Presenter will be the Observer subscribe to changes on the state of the Model. 演示者将使用此呈现器使观察者订阅对模型状态的更改。 The thing is, the presenter will execute the updates in the model, accordingly to the events occurred in the view. 问题是,演示者将根据视图中发生的事件执行模型中的更新。 Every time that the presenter executes one method in.the model, It will be. 演示者每次在模型中执行一种方法时,它都会。 possible to change its state and notify the presenter. 可以更改其状态并通知演示者。 I will separate then in another thread the model for every update, but how can I notify the presenter if this is running in a different thread inside a while loop? 然后,我将在另一个线程中为每次更新分离模型,但是如果它在while循环内的另一个线程中运行,我如何通知演示者? If I call the method notify observers, when the presenter will call the corresponding method? 如果我调用该方法通知观察者,演示者何时会调用相应的方法?

Its driving me crazy! 这让我疯狂! :PI need your help captains! :PI需要您的帮助队长!

It's possible you are over engineering this in terms of architecture. 您可能会在体系结构方面过度设计。 MVP and Producer/Consumer and Observable all in the same post. MVP与生产者/消费者和可观察者都在同一帖子中。 Alarm bells are ringing. 警钟响起。 I suspect that you don't need the producer/consumer or the observer pattern, MVP is probably totally adequate. 我怀疑您不需要生产者/消费者或观察者模式,MVP可能就足够了。

Try this. 尝试这个。

Create 3 files: 创建3个文件:

  • GameFragment.java GameFragment.java
  • GameView.java GameView.java
  • GamePresenter.java GamePresenter.java

GamePresenter: GamePresenter:

public class GamePresenter {
    private final GameView view;

    public GamePresenter(GameView view){
        this.view = view;
        NetworkController.addObserver(this);//listen for events coming from the other player for example. 
    }

    public void onSwipeRight(){
        // blah blah do some logic etc etc
        view.moveRight(100);
        NetworkController.userMovedRight();
    }

    public void onNetworkEvent(UserLeftGameEvent event){
        // blah blah do some logic etc etc
        view.stopGame()
    }
}

GameView GameView

is an interface 是一个接口

public interface GameView {
    void stopGame();
    void moveRight(int pixels);
}

GameFragment is a class that extends Fragment and implements GameView AND has a GamePresenter as a member. GameFragment是扩展Fragment并实现GameView的类,并具有GamePresenter作为成员。

public class GameFragment extends Fragment implements GameView {
    private GamePresenter presenter;

    @Override
    public void onCreate(Bundle savedInstanceState){
        presenter = new GamePresenter(this);
    }
}

The key to this approach is to clearly understand the role of each file. 该方法的关键是清楚地了解每个文件的角色。

The Fragment is in control of anything view related (Buttons, TextView etc). Fragment可以控制任何与视图相关的内容(按钮,TextView等)。 It informs the presenter of user interactions. 通知演示者用户交互。

The Presenter is the engine, it takes the information from the View (in this case it is the Fragment, but notice that this pattern lends itself well to Dependency injection? That's no coincidence. The Presenter doesn't know that the View is a Fragment - it doesn't care) and combines it with the information it is receiving from 'below' (comms, database etc) and then commands the View accordingly. Presenter是引擎,它从View中获取信息(在本例中为Fragment,但是请注意,该模式很适合于依赖注入吗?这不是巧合。Presenter不知道View是一个Fragment。 -无关紧要),并将其与从“下面”(通信,数据库等)接收的信息合并,然后相应地命令 View。

The View is simply an interface through which the Presenter communicates with the View. 视图只是演示者通过其与视图通信的界面。 Notice that the methods read as commands , not as questions (eg getViewState()) and not to inform (eg onPlayerPositionUpdated()) - commands (eg movePlayerHere(int position)). 注意,这些方法读为命令而不是 问题 (例如getViewState()),而不是 通知 (例如onPlayerPositionUpdated())- 命令 (例如movePlayerHere(int position))。

It Doesn't matter. 没关系 You have an object, Presenter , which is being used inside an infinite loop inside a thread. 您有一个对象Presenter ,该对象正在线程的无限循环内使用。 That does not mean you cannot call it's methods while its being called by the thread as well. 这并不意味着您也无法在线程调用它的同时调用它的方法。 The only consideration you have to take care of is that, if the data being read/used by the thread is the same altered by the observer notification, you shoud synchronize it access. 您唯一需要注意的是,如果线程读取/使用的数据与观察者通知更改的内容相同,则应同步访问。

So, to summarize, while the Presenter is running inside the infinite loop, any call to it's method will be answered instantly (unless they have synchronized access, in which case it will block until it gets the lock ownership) 因此,总而言之,当Presenter在无限循环内运行时,对其方法的任何调用都将立即得到答复(除非它们具有同步访问权限,在这种情况下,它将阻塞直到获得锁所有权为止)

The following is completly fine: 完全可以满足以下条件:

class Presenter implements IObserver
{
    public void aMethod() { }

    public void notifyObserver() { }
}

class Model
{
    private List<IObserver> observers = new ArrayList<>();

    public void addObserver(IObserver obs) { observers.add(obs); }

    public void notifyObservers()
    {
        for(IObserver o : observers) { o.notifyObserver(); }
    }
}


final Presenter myPresenter = new Presenter();
Model myModel = new Model();
myModel.add(myPresenter);

new Thread(new Runnable() 
{
    @Override
    public void run()
    {
        while(true)
        {
            myPresenter.aMethod();
        }           
    }
).start();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM