当前位置: 首页 > 面试题库 >

是否存在使用GWT在MVP中使用观察者模式的推荐方法?

卫仲卿
2023-03-14
问题内容

我正在考虑使用GWT根据MVP模式实现用户界面,但对如何进行操作有疑问。

这些是我的一些目标:

  • 演示者对UI技术一无所知(即不使用com.google。*)
  • 该视图对演示者一无所知(尚不确定我是否希望它与模型无关)
  • 模型不了解视图或演示者(显然)

我将在视图和演示者之间放置一个接口,并使用Observer模式将两者分离:视图生成事件,并且演示者得到通知。

令我感到困惑的是,GWT不支持java.util.Observer和java.util.Observable。这表明,就GWT而言,我不建议这样做,这引出了我的问题:使用GWT实施MVP的推荐方法是什么,尤其是考虑到上述目标?你会怎么做?


问题答案:

这就是我做的。该Eventbus让主持人(扩展抽象类Subscriber)订阅属于不同的事件 模块 在我的应用程序。每个 模块
对应于我系统中的一个组件,并且每个模块都有一个事件类型,一个演示者,一个处理程序,一个视图和一个模型。

订阅所有类型的事件的演示者CONSOLE将接收从该模块触发的所有事件。对于更细粒度的方法,您总是可以让演示者订阅特定的事件,例如NewLineAddedEvent诸如此类,但是对于我来说,我发现在模块级别进行处理就足够了。

如果愿意,可以异步调用演示者的紧急救援方法,但是到目前为止,我发现自己几乎不需要这样做。我想这取决于您的确切需求。这是我的EventBus

public class EventBus implements EventHandler 
{
    private final static EventBus INSTANCE = new EventBus();
    private HashMap<Module, ArrayList<Subscriber>> subscribers;

    private EventBus()  
    { 
      subscribers = new HashMap<Module, ArrayList<Subscriber>>(); 
    }

    public static EventBus get() { return INSTANCE; }

    public void fire(ScEvent event)
    {
        if (subscribers.containsKey(event.getKey()))
            for (Subscriber s : subscribers.get(event.getKey()))
                s.rescue(event);
    }

    public void subscribe(Subscriber subscriber, Module[] keys)
    {
        for (Module m : keys)
            subscribe(subscriber, m);
    }

    public void subscribe(Subscriber subscriber, Module key)
    {
        if (subscribers.containsKey(key))
            subscribers.get(key).add(subscriber);
        else
        {
            ArrayList<Subscriber> subs = new ArrayList<Subscriber>();
            subs.add(subscriber);
            subscribers.put(key, subs);
        }
    }

    public void unsubscribe(Subscriber subscriber, Module key)
    {
        if (subscribers.containsKey(key))
            subscribers.get(key).remove(subscriber);
    }

}

处理程序连接到组件,并负责将本地GWT事件转换为专门用于我的系统的事件。下面的处理程序ClickEvents只需将它们包装在自定义事件中,然后将其触发以EventBus供订阅者处理即可。在某些情况下,对于处理程序来说,在触发事件之前甚至有时在确定天气或不发送事件之前执行额外的检查是有意义的。当将处理程序添加到图形组件时,将给出处理程序中的操作。

public class AppHandler extends ScHandler
{
    public AppHandler(Action action) { super(action); }

    @Override
    public void onClick(ClickEvent event) 
    { 
         EventBus.get().fire(new AppEvent(action)); 
    }

Action是一个枚举,表示系统中数据操作的可能方式。每个事件都以初始化Action。演示者使用该操作来确定如何更新其视图。具有操作的事件ADD可能会使演示者向菜单添加新按钮,或向网格添加新行。

public enum Action 
{
    ADD,
    REMOVE,
    OPEN,
    CLOSE,
    SAVE,
    DISPLAY,
    UPDATE
}

处理程序触发的事件看起来像这样。请注意,事件是如何为其使用者定义接口的,这将确保您不会忘记实施正确的救援方法。

public class AppEvent extends ScEvent {

    public interface AppEventConsumer 
    {
        void rescue(AppEvent e);
    }

    private static final Module KEY = Module.APP;
    private Action action;

    public AppEvent(Action action) { this.action = action; }

演示者订阅了属于不同模块的事件,然后在它们被激发时对其进行抢救。我还让每个演示者为其视图定义一个接口,这意味着演示者将永远不必了解实际的图形元素。

public class AppPresenter extends Subscriber implements AppEventConsumer, 
                                                        ConsoleEventConsumer
{
    public interface Display 
    {
        public void openDrawer(String text);
        public void closeDrawer();
    }

    private Display display;

    public AppPresenter(Display display)
    {
        this.display = display;
        EventBus.get().subscribe(this, new Module[]{Module.APP, Module.CONSOLE});
    }

    @Override
    public void rescue(ScEvent e) 
    {
        if (e instanceof AppEvent)
            rescue((AppEvent) e);
        else if (e instanceof ConsoleEvent)
            rescue((ConsoleEvent) e);
    }
}

每个视图都有一个实例,该实例HandlerFactory负责为每个视图创建正确类型的处理程序。每个工厂都以实例化,Module用于创建正确类型的处理程序。

public ScHandler create(Action action)
{
  switch (module)
  {
    case CONSOLE :
      return new ConsoleHandler(action);

该视图现在可以自由地向其组件添加不同类型的处理程序,而无需了解确切的实现细节。在此示例中,所有视图需要知道的是addButton按钮应该链接到与action对应的某些行为ADD。这种行为的方式将由捕获事件的演示者决定。

public class AppView implements Display

   public AppView(HandlerFactory factory)
   {
       ToolStripButton addButton = new ToolStripButton();
       addButton.addClickHandler(factory.create(Action.ADD));
       /* More interfacy stuff */  
   }

   public void openDrawer(String text) { /*Some implementation*/ }
   public void closeDrawer() {  /*Some implementation*/ }

考虑一个简化的Eclipse,其中您有一个类层次结构在左侧,一个代码文本区域在右侧,而菜单栏位于顶部。这三个是由三个不同的演示者组成的三个不同的视图,因此它们将构成三个不同的模块。现在,完全有可能需要根据类层次结构中的更改来更改文本区域,因此,对于文本区域演示者来说,不仅要订阅从文本区域内触发的事件,而且还要订阅事件,这是有意义的从类层次结构中被解雇。我可以想象这样的事情(每个模块会有一组类-
一个处理程序,一个事件类型,一个演示者,一个模型和一个视图):

public enum Module 
{
   MENU,
   TEXT_AREA,
   CLASS_HIERARCHY
}

现在考虑我们希望我们的视图在从层次结构视图中删除类文件时正确更新。这将导致对gui进行以下更改:

  1. 该类文件应从类层次结构中删除
  2. 如果类文件已打开,因此在文本区域中可见,则应将其关闭。

两名演示者,一个控制树视图,一个控制文本视图,都将订阅从CLASS_HIERARCHY模块触发的事件。如果事件的动作是REMOVE,则两个主持人都可以采取适当的动作,如上所述。控制层次结构的演示者可能还会向服务器发送一条消息,以确保已删除的文件实际上已被删除。此设置允许模块仅通过侦听从事件总线触发的事件来对其他模块中的事件做出反应。进行的耦合很少,交换视图,演示者或处理者是完全轻松的。



 类似资料:
  • 我有一个系统(游戏),我尝试使用架构模型视图呈现器来实现它。我现在所做的是演示者中的while循环,它不断调用视图方法来显示。我这样做的方式是使用Producer/Consumer模式,其中View为触摸事件(Android)注册和事件处理程序,并生成相应的触摸实例,演示者在while循环中使用。 现在我想在模型和演示者之间使用模式观察者/Suscriber。使用这个模式,演示者将是观察者订阅模型

  • 本文向大家介绍Javascript设计模式之观察者模式(推荐),包括了Javascript设计模式之观察者模式(推荐)的使用技巧和注意事项,需要的朋友参考一下 推荐阅读: JavaScript观察者模式(经典) 1.什么是观察者模式 观察者模式有时也称为发布--订阅模式,在观察者模式中,有一个观察者可以管理所有的目标,等到有状态发生改变的时候发出通知。(其实sql server中的发布订阅也是这个

  • 我来自同步编程背景,我很难理解可观察性。 这是我的服务/提供商的摘录(离子2项目) 我将从订阅它。关于这一点,我有几个问题。 > 即使我没有声明,上面的代码是否返回一个可观察/观察者? 响应是JSON。如何检查/处理JSON并执行一些操作,如 那就做吧 我认为应该在提供者类中完成。只是一个典型的提示/例子将是真棒。 当请求到达subscribe方法时,它是否真的发生了? 创建和返回Angular

  • 我已经开始学习RxJava和RxAndroid。我想用RxJava替换我的观察者模式。observer模式类似于Android LocationManager类,该类具有register和unregister方法。“observable”类(不意味着rx.observable)在其自己的线程(HandlerThread)中工作,并拥有监听器及其处理程序对象的映射,每个监听器都在其线程中调用(通过处

  • 主要内容:介绍,实现,Subject.java,Observer.java,BinaryObserver.java,OctalObserver.java,HexaObserver.java,ObserverPatternDemo.java当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。 介绍 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知

  • 观察者模式 亦称: 事件订阅者、监听者、Event-Subscriber、Listener、Observer 意图 观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。 问题 假如你有两种类型的对象: ​ 顾客和 商店 。 顾客对某个特定品牌的产品非常感兴趣 (例如最新型号的 iPhone 手机), 而该产品很快将会在商店里出售。 顾客