MVP 中的观察者模式
Observer Pattern in MVP
我有一个系统(游戏),我尝试使用架构 Model-View-Presenter 来实现它。我现在所做的是演示者中的 while 循环,它不断调用用于显示的视图方法。我这样做的方法是使用 Producer/Consumer 模式,其中视图为触摸事件 (Android) 注册和事件处理程序并生成相应的触摸实例,演示者在 while 循环中使用这些实例。
现在我想在模特和主持人之间使用模式 Observer/Suscriber。使用此 Presenter 将成为 Observer 订阅模型状态的更改。问题是,演示者将根据视图中发生的事件在模型中执行更新。每次演示者执行一个方法 in.the 模型时,它就会。可以更改其状态并通知演示者。然后我将在另一个线程中分离每个更新的模型,但是 如果这是 运行 在 while 循环内的不同线程中,我如何通知演示者?如果我调用notify observers的方法,presenter会在什么时候调用相应的方法?
快把我逼疯了! :P 我需要船长们的帮助!
没关系。您有一个对象 Presenter
,它正在线程内的无限循环中使用。这并不意味着您不能在它被线程调用时调用它的方法。您唯一需要注意的是,如果线程 read/used 中的数据与观察者通知更改的相同,您应该同步它的访问。
所以,总而言之,虽然 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();
您可能在架构方面设计过度了。 MVP 和 Producer/Consumer 以及 Observable 都在同一个 post 中。警钟长鸣。我怀疑您不需要 producer/consumer 或观察者模式,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 是一个 class,它扩展了 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 不知道 View 是一个 Fragment——它不在乎)并将它与从 'below'(通信、数据库等)接收的信息结合起来,然后 命令相应的视图。
View 只是一个接口,Presenter 通过它与 View 进行通信。请注意,这些方法读作 commands,not 读作 questions(例如 getViewState())和 not 到 inform(例如 onPlayerPositionUpdated())- commands(例如 movePlayerHere(int position))。
我有一个系统(游戏),我尝试使用架构 Model-View-Presenter 来实现它。我现在所做的是演示者中的 while 循环,它不断调用用于显示的视图方法。我这样做的方法是使用 Producer/Consumer 模式,其中视图为触摸事件 (Android) 注册和事件处理程序并生成相应的触摸实例,演示者在 while 循环中使用这些实例。
现在我想在模特和主持人之间使用模式 Observer/Suscriber。使用此 Presenter 将成为 Observer 订阅模型状态的更改。问题是,演示者将根据视图中发生的事件在模型中执行更新。每次演示者执行一个方法 in.the 模型时,它就会。可以更改其状态并通知演示者。然后我将在另一个线程中分离每个更新的模型,但是 如果这是 运行 在 while 循环内的不同线程中,我如何通知演示者?如果我调用notify observers的方法,presenter会在什么时候调用相应的方法?
快把我逼疯了! :P 我需要船长们的帮助!
没关系。您有一个对象 Presenter
,它正在线程内的无限循环中使用。这并不意味着您不能在它被线程调用时调用它的方法。您唯一需要注意的是,如果线程 read/used 中的数据与观察者通知更改的相同,您应该同步它的访问。
所以,总而言之,虽然 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();
您可能在架构方面设计过度了。 MVP 和 Producer/Consumer 以及 Observable 都在同一个 post 中。警钟长鸣。我怀疑您不需要 producer/consumer 或观察者模式,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 是一个 class,它扩展了 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 不知道 View 是一个 Fragment——它不在乎)并将它与从 'below'(通信、数据库等)接收的信息结合起来,然后 命令相应的视图。
View 只是一个接口,Presenter 通过它与 View 进行通信。请注意,这些方法读作 commands,not 读作 questions(例如 getViewState())和 not 到 inform(例如 onPlayerPositionUpdated())- commands(例如 movePlayerHere(int position))。