gwt的mvp模式_GWT MVP变得简单

gwt的mvp模式

GWT Model-View-Presenter是用于大规模应用程序开发的设计模式。 它源于MVC,它在视图和逻辑之间进行划分,并有助于创建结构良好,易于测试的代码。 为了帮助像我这样的懒惰开发人员,我研究了如何减少使用声明式UI时要编写的类和接口的数量。

经典MVP

您知道如何在Facebook中发布链接吗? –最近,我不得不为一个小GWT旅行应用程序创建此功能。

因此,您可以输入一个URL,然后将其提取并解析。 您可以从页面中选择图像之一,查看文本,最后存储链接。
现在如何在MVP中正确设置此设置? –首先,创建一个类似于视图的抽象接口:

interface Display {HasValue<String> getUrl();void showResult();HasValue<String> getName();HasClickHandlers getPrevImage();HasClickHandlers getNextImage();void setImageUrl(String url);HasHTML getText();HasClickHandlers getSave();
}

它利用GWT组件实现的接口来提供对其状态和功能的某些访问。 在测试期间,您无需参考GWT内部即可轻松实现此接口。 同样,可以在不影响更深层逻辑的情况下更改视图实现。
该实现非常简单,此处显示了声明的UI字段:

class LinkView implements Display@UiField TextBox url;@UiField Label name;@UiField VerticalPanel result;@UiField Anchor prevImage;@UiField Anchor nextImage;@UiField Image image;@UiField HTML text;@UiField Button save;public HasValue<String> getUrl() {return url;}public void showResult() {result.setVisible(true);}// ... and so on ...
}

然后,演示者使用接口访问视图,按照惯例,该接口写在presenter类中:

class LinkPresenterinterface Display {...};public LinkPresenter(final Display display) {display.getUrl().addValueChangeHandler(new ValueChangeHandler<String>() {@Overridepublic void onValueChange(ValueChangeEvent<String> event) {Page page = parseLink(display.getUrl().getValue());display.getName().setValue(page.getTitle());// ...display.showResult();}});}// ... and so on ...
}

因此,我们在这里:使用MVP,您可以很好地组织代码并使代码易于阅读。

简化

收益是: 每个屏幕或组件三种类型 。 每当重新定义UI时,三个文件都将更改。 未将ui.xml文件计为视图声明。 对于像我这样的懒人来说,这些太多了。 并且,如果您查看视图实现,很明显如何简化它:
使用视图声明(* .ui.xml)作为视图,并将ui元素直接注入到presenter中:

class LinkPresenter@UiField HasValue<String> url;@UiField HasValue<String> name;@UiField VerticalPanel result;@UiField HasClickHandlers prevImage;@UiField HasClickHandlers nextImage;@UiField HasUrl image;@UiField HasHTML text;@UiField HasClickHandlers save;public LinkPresenter(final Display display) {url.addValueChangeHandler(new ValueChangeHandler<String>() {@Overridepublic void onValueChange(ValueChangeEvent<String> event) {Page page = parseLink(url.getValue());name.setValue(page.getTitle());// ...result.setVisible(true);}});}// ... and so on ...
}

由于可以使用它们的接口声明注入的元素,因此此演示者具有成熟的MVP演示者的许多优点:您可以通过设置实现组件来对其进行测试(请参见下文),并且可以轻松地更改视图实现。
但是现在,您将所有这些都放在一个类和一个view.ui.xml文件中,并且可以更简单地应用结构更改。

使UI元素抽象

TextBox实现HasValue <String>。 这很简单。 但是,不能通过接口访问的ui元素的属性呢? 您可能已经认识到的示例是上述代码中的VerticalPanel命名结果result及其方法setVisible(),不幸的是,该方法在UiObject基类中实现。 因此,没有可用的接口,例如。 在测试时实施。 为了能够切换视图实现,最好注入ComplexPanel,但是即使在测试时也无法实例化。

例如,在这种情况下,唯一的出路是创建一个新接口

interface Visible {void setVisible(boolean visible);boolean isVisible();
}

和子类化有趣的UI组件,实现相关的接口:

package de.joergviola.gwt.tools;
class VisibleVerticalPanel extends VerticalPanel implements Visible {}

这似乎是乏味和次优的。 但是,只能像上述成熟的MVP中那样,仅针对每个组件而不是针对每个视图进行操作。
等待-如何在UiBuilder模板中使用自制组件? –很简单:

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:t="urn:import:de.joergviola.gwt.tools"><g:VerticalPanel width="100%"><g:TextBox styleName="big" ui:field="url" width="90%"/><t:VisibleVerticalPanel ui:field="result"visible="false"  width="100%"></t:VisibleVerticalPanel></g:VerticalPanel>
</ui:UiBinder>

声明处理程序

声明(click-)处理程序的标准方法非常方便:

@UiHandler("login")public void login(ClickEvent event) {srv.login(username.getValue(), password.getValue());}

在简化的MVP方法中,此代码将驻留在演示者中。 但是ClickEvent参数是View组件,可以例如。 不能在运行时实例化。 另一方面,由于UiBuilder需要Event参数,因此无法从签名中将其删除。

因此,不幸的是,您必须坚持手动注册ClickHandlers(因为无论如何都必须执行完整的MVP):

public initWidget() {...login.addClickHandler(new ClickHandler() {@Overridepublic void onClick(ClickEvent event) {login();}});...
}public void login(ClickEvent event) {srv.login(username.getValue(), password.getValue());
}

测试中
引入MVP时,使您的应用程序可测试是主要目标之一。
GwtTestCase能够在容器环境中执行测试,但需要一些启动时间。 在TDD中,希望有一个运行速度非常快的测试,可以在每次更改后应用它而不会丢失上下文。 因此,MVP旨在能够在标准JVM中测试所有代码。 在标准MVP中,您将创建视图接口的实现。 在这种简化方法中,只需在组件接口级别创建实现即可,如下所示:

class Value<T> implements HasValue<T> {private T value;List<ValueChangeHandler<T>> handlers = new ArrayList<ValueChangeHandler<T>>();@Overridepublic HandlerRegistration addValueChangeHandler(ValueChangeHandler<T> handler) {handlers.add(handler);return null;}@Overridepublic void fireEvent(GwtEvent<?> event) {for (ValueChangeHandler<T> handler : handlers) {handler.onValueChange((ValueChangeEvent) event);}}@Overridepublic T getValue() {return value;}@Overridepublic void setValue(T value) {this.value = value;}@Overridepublic void setValue(T value, boolean fireEvents) {if (fireEvents)ValueChangeEvent.fire(this, value);setValue(value);}}

与往常一样,您必须将此组件注入到被测演示者中。 尽管从原则上讲,您可以为组件创建一个设置器,但我仍然遵循通常的技巧来使组件受包保护,将测试与演示者放入同一包中(但当然是不同的项目文件夹),然后直接设置组件。

你赢了什么?

您得到的代码结构像完整的MVP一样干净,只需要少得多的类和样板代码。
在某些情况下,组件及其接口需要实用程序类,但是随着时间的流逝,您将构建一个真正易于理解,测试和扩展的环境。

我很好奇:告诉我您的经历!

参考: JWT合作伙伴 简化了GWT MVP   Joerg Viola在Joerg Viola博客上 。


翻译自: https://www.javacodegeeks.com/2012/02/gwt-mvp-made-simple.html

gwt的mvp模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356532.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简记用ArcGIS处理某项目需求中数据的步骤

文章版权由作者李晓晖和博客园共有&#xff0c;若转载请于明显处标明出处&#xff1a;http://www.cnblogs.com/naaoveGIS/ 1. 背景 项目需求涉及如下几个步骤&#xff1a; a.矢量化 b.获取范围内要素 c.合并要素 d.简化要素 e.获取范围外要素。 2. 矢量化 新建图层 开启编辑&am…

从python学编程pdf_教孩子学编程-Python语言版 PDF 高清完整版 网盘资源分享

提取码&#xff1a;2hrr内容简介 本书属于no starch的经典系列之一&#xff0c;英文版在美国受到读者欢迎。本书全彩印刷&#xff0c;寓教于乐&#xff0c;易于学习&#xff1b;读者可以轻松与快递地掌握解决问题方法和程序设计思维的。“编程从孩子抓起”得到越来越多的…

vertical-align属性详解

vertical-align属性详解:http://www.cnblogs.com/wcp-spring/archive/2013/03/04/2942456.html 关于vertical-align属性&#xff1a;http://www.cnblogs.com/hykun/p/3937852.html 对于vertical-align&#xff1a;middle&#xff1b;的使用&#xff1a;http://www.tuicool.com/…

企业应用程序集成简介

本文是我们名为“ Spring Integration for EAI ”的学院课程的一部分。 在本课程中&#xff0c;向您介绍了企业应用程序集成模式以及Spring Integration如何解决它们。 接下来&#xff0c;您将深入研究Spring Integration的基础知识&#xff0c;例如通道&#xff0c;转换器和适…

python实现用户输入用户名和密码不能为空_Python学习【第四篇】用户输入及判断...

用户输入:例1。写一个小程序为用户输入密码。流程如下:1。用户输入其用户名2。输出\u201CHello 用户名\\/usr\/bin\/env python # name raw_input(\u201C你叫什么名字?\u201D)只在pythonname # 输入(\u201C你叫什么名字?\u201D)打印(\u201CHello\u201D名字)例2。当输入一个密…

win7 网络端口怎么设置_教你win7如何设置网络共享文件夹

网络共享是以PC机为载体的信息资源共享。如果我们想让其他人共享我们的文件夹&#xff0c;我们需要进行一些设置。今天&#xff0c;我将分享在win7系统中设置网络共享文件夹的方法现在大多数家庭都使用win7系统&#xff0c;它简化了很多设计&#xff0c;使用起来也很方便。它不…

junit testng_TestNG或JUnit

junit testng多年以来&#xff0c;无论何时使用Java代码进行单元测试&#xff0c;我始终会回到TestNG。 每当我拿起TestNG时&#xff0c;人们都会问我为什么要继续使用TestNG&#xff0c;尤其是默认开发环境&#xff08;例如Eclipse或Maven&#xff09;提供的JUnit时。 继续进行…

背单词

背单词 (word.c/cpp/pas) 【题目描述】 fqk 退役后开始补习文化课啦&#xff0c; 于是他打开了英语必修一开始背单词。 看着满篇的单词非常头疼&#xff0c; 而每次按照相同的顺序背效果并不好&#xff0c;于是 fqk 想了一种背单词的好方法&#xff01;他把单词抄写到一个 n 行…

vue 字符串分割_嗯哼vue组件taginput包教不包会

5分钟实现一个Tag-Input(标签)组件前言本文是wo写组件设计的第一篇文章(处女作)&#xff0c;之所以会写组件设计相关的文章,是因为作为一名优秀的前端工程师&#xff0c;面对各种繁琐而重复的工作&#xff0c;我们不应该按部就班的去辛(dao)勤(gen)劳(huo)动(zhong)&#xff0c…

一元操作符——递增和递减操作符(第一次写博客,紧张.)

一元操作符&#xff0c;即只能操作一个值的操作符&#xff0c;是JS中最简单的操作符。 1.递增和递减操作符 分为2个版本&#xff1a;前置型和后置型。若使用前置递增操作符给一个数值加1&#xff0c;要把&#xff08;&#xff09;放在数值前面&#xff1a; var a 1;a; > va…

Spring 4.2中由注释驱动的事件侦听器

介绍 在应用程序内交换事件已成为许多应用程序中必不可少的部分&#xff0c;幸运的是&#xff0c;Spring为瞬态事件&#xff08;*&#xff09;提供了完整的基础结构。 最近对事务绑定事件的重构为我提供了一个借口&#xff0c;以在实践中检查Spring 4.2中引入的新的注释驱动事件…

mysql插入数据不成功_mysql插入数据失败原因分析

今天在做一个项目时&#xff0c;就是把一个数据库里面的资料导入到另一个数据库里面。想想很简单啊&#xff0c;就是用sql语句&#xff0c;把一个数据库里面数据select读取出来,然后循环update到另一个数据库里面。其实操作起来也很简单的&#xff0c;但是中途出现了问题&#…

SpringBoot项目部署与服务配置

spring Boot 其默认是集成web容器的&#xff0c;启动方式由像普通Java程序一样&#xff0c;main函数入口启动。其内置Tomcat容器或Jetty容器&#xff0c;具体由配置来决定&#xff08;默认Tomcat&#xff09;。当然你也可以将项目打包成war包&#xff0c;放到独立的web容器中&a…

mysql排序两位数_MySQL_Mysql row number()排序函数的用法和注意,虽然使用不多,但是也有情况 - phpStudy...

Mysql row number()排序函数的用法和注意虽然使用不多&#xff0c;但是也有情况是需要在mysql 里面写语句开发功能的。在sql server 使用惯了&#xff0c;习惯了使用row_number() 函数进行排序&#xff0c;但是mysql 确没有这样一个函数。然后找到了po主写的一篇 文章。通过变量…

UIView动画效果

UIView是iOS系统中界面元素的基础, 所有的界面元素都是继承自它.它本身完全由CoreAnimation来实现的.它真正的绘图部分,是由一个CALayer类来管理.UIView本身更像一个CALayer的管理器,访问它的跟绘图和坐标有关的相关属性. iOS的画面切换效果的API主要通过调用系统已定义的动画效…

mysql bin.000047_mysql-bin.0000X 日志文件处理

一、清除文件[rootjiucool var]# /usr/local/mysql/bin/mysql -u root -pEnter password: (输入密码)Welcome to the MySQL monitor. Commands end with ; or /g.Your MySQL connection id is 264001Server version: 5.1.35-log Source distributionType ‘help;’ or ‘/h’…

向导页设计_向导设计模式

向导页设计我们都喜欢巫师……。 &#xff08;我的意思是软件向导&#xff09;。 我们总是很高兴跳到那些“下一步”按钮上&#xff0c;就像我们在我们的时髦的小鸡上跳舞一样。。。 因此&#xff0c;今天我们将您心爱的向导带入您的编码体验。 让我们跳入一个例子。 假设您要设…

Java第十天

线程间通讯&#xff1a; 多个线程在处理同一资源&#xff0c;但是任务却不同。 多生产者&#xff0c;多消费者的问题&#xff1a; if判断标记&#xff0c;只有一次&#xff0c;会导致不该运行的线程运行了。出现了数据错误的情况。 while判断标记&#xff0c;解决了线程获取执行…

使用Apache Drill深入研究当今的大数据

自2014年9月首次提供Beta版以来&#xff0c; Apache Drill一直在获得广泛的用户采用和社区动力。2015年5月发布了Drill的通用版本-Drill 1.0&#xff0c;此后&#xff0c;许多客户已在生产中部署和使用了Drill。 在此博客文章中&#xff0c;我将简要总结客户在Drill中发现的宝贵…

mysql grep 提取错误日志_详解grep获取MySQL错误日志信息的方法

为方便维护MySQL&#xff0c;写了个脚本用以提供收集错误信息的接口。这些错误信息来自与MySQL错误日志&#xff0c;而 通过grep mysql可以获取error-log的路径。以下是全部相关代码&#xff1a;#!/usr/bin/env python2.7#-*- encoding: utf-8 -*-"""该模块用于…