【问题标题】:Observer Pattern in MVPMVP 中的观察者模式
【发布时间】:2016-08-15 18:29:28
【问题描述】:

我有一个系统(游戏),我尝试使用 Model-View-Presenter 架构来实现它。我现在所做的是演示者中的一个while循环,它不断调用视图方法进行显示。我这样做的方法是使用生产者/消费者模式,其中视图注册和触摸事件的事件处理程序(Android)并产生相应的触摸实例,演示者在 while 循环中使用。

现在我想在模型和演示者之间使用观察者/订阅者模式。使用它,Presenter 将成为 Observer 订阅模型状态的更改。问题是,演示者将根据视图中发生的事件执行模型中的更新。每次演示者在模型中执行一个方法时,它都会。可以更改其状态并通知演示者。然后,我将在另一个线程中分离每个更新的模型,但是 如果它在 while 循环内的不同线程中运行,我如何通知演示者?如果我调用方法notifyobservers,那么presenter什么时候调用对应的方法?

它快把我逼疯了! :P 我需要你的帮助队长!

【问题讨论】:

    标签: java android model-view-controller observer-pattern


    【解决方案1】:

    没关系。您有一个对象Presenter,它在线程内的无限循环中使用。这并不意味着您不能在线程调用它的同时调用它的方法。您需要注意的唯一考虑因素是,如果线程正在读取/使用的数据与观察者通知更改的数据相同,则您应该同步它的访问。

    因此,总而言之,当Presenter 在无限循环中运行时,对其方法的任何调用都会立即得到响应(除非它们具有同步访问,在这种情况下它将阻塞直到获得锁所有权)

    以下完全没问题:

    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();
    

    【讨论】:

    • 哦!就这样解决了! :) 问题是演示者本身正在一个单独的线程上运行一个更新方法,在一个while循环内,您的解决方案看起来更清晰,在另一个托管线程的对象中使用更新方法!这就是我所缺少的。因此,在这种情况下,如果我必须通知演示者,则可以参加通话,并且不会运行循环。太聪明了,谢谢!!!!
    【解决方案2】:

    您可能在架构方面过度设计了它。 MVP、Producer/Consumer 和 Observable 都在同一篇文章中。警钟正在敲响。我怀疑你不需要生产者/消费者或观察者模式,MVP 可能完全足够了。

    试试这个。

    创建 3 个文件:

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

    游戏演示者:

    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()
        }
    }
    

    游戏视图

    是一个接口

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

    GameFragment 是一个扩展 Fragment 并实现 GameView 并且有一个 GamePresenter 作为成员的类。

    public class GameFragment extends Fragment implements GameView {
        private GamePresenter presenter;
    
        @Override
        public void onCreate(Bundle savedInstanceState){
            presenter = new GamePresenter(this);
        }
    }
    

    这种方法的关键是清楚地了解每个文件的作用。

    Fragment 可以控制任何与视图相关的内容(按钮、TextView 等)。它通知用户交互的演示者。

    Presenter 是引擎,它从 View 获取信息(在本例中是 Fragment,但请注意这种模式很适合依赖注入?这绝非巧合。Presenter不知道视图是一个片段 - 它不在乎)并将它与它从“下面”(通讯、数据库等)接收的信息相结合,然后相应地命令视图。

    视图只是一个界面,Presenter 通过它与视图进行通信。请注意,这些方法读作 commandsnot 读作 questions(例如 getViewState()),而 not 读作 inform (例如 onPlayerPositionUpdated()) - 命令 (例如 movePlayerHere(int position))。

    【讨论】:

    • 哦,我的想法是使用第一个模式生产者/消费者在视图和演示者之间进行通信。但是,如果我要让演示者与模型完全分离,那么模型必须对演示者一无所知,所以我正在考虑以事件格式保存合同,模型将使用该事件将其状态传达给演示者,所以演示者可以相应地更新视图:)。所以演示者正在运行一个while循环,从视图接收事件,更新模型,更新视图,等等。你认为这是一个糟糕的实现
    猜你喜欢
    • 2016-02-20
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 2014-10-14
    • 1970-01-01
    • 2013-04-11
    • 2011-03-30
    相关资源
    最近更新 更多