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…

企业应用程序集成简介

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

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

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

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

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

SpringBoot项目部署与服务配置

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

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

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

微信小程序需要https后台的创业机会思考

最近比较关注微信小程序&#xff0c;而且微信小程序的后台必须强制要求https&#xff0c; https相对http成本要高很多了。 这里我感觉有2个商机 &#xff08;1&#xff09;提供https 中转服务器 ,按流量来收费 &#xff08;2&#xff09; 微信小程序https 云后台 对于很多人学…

aspx是什么语言_什么是网页

第一个问题&#xff0c;什么是网页&#xff1f;我们通常在网上浏览的所有网页都是网页&#xff0c;一个网站由一页到50页不等的网页组成&#xff0c;一些大型网站可能包含数千万页&#xff0c;是第一个打开网站的网站。这些页面被称为主页。专有名词:这里简要介绍网页、网站和主…

mysql运算结果放入表中_MySQL表1新增数据,计算开始、结束日期之间所有时间,插入到表2中...

新建表c3#id设置自增量&#xff0c;kk是要同步的一些数据值&#xff0c;dd是开始时间&#xff0c;dde是结束时间CREATE TABLE c3 (id int(11) NOT NULL auto_increment PRIMARY KEY,kk varchar(255),dd datetime,dde datetime)新建表c4#id也设置自增量&#xff0c;kk是要同步…

longtext长度为0是什么意思_为什么 HashMap 中链表长度大于 8 才转化为红黑树?

Java 中的 HashMap 采用链表法来解决哈希冲突&#xff08;HashMap 原理&#xff09;&#xff0c;即具有相同桶下标的键值对使用一个链表储存。当链表变长时&#xff0c;查找和添加&#xff08;需要确定 key 是否已经存在&#xff09;都需要遍历这个链表&#xff0c;速度会变慢。…

python图形界面教程_图形教程

python图形界面教程众所周知&#xff0c;我们可以借助Java库制作游戏&#xff0c;这些库为我们提供制作游戏所需的图形。 因此&#xff0c;今天我将开始一个关于Java图形的非常新的部分。 我之前曾发表过有关如何制作所得税计算器的文章 。 首先要满足一些先决条件&#xff1a;…

java创建树结构_Java学习之XML-017

如果想快速有效的学习&#xff0c;思想核心是“以建立知识体系为核心”&#xff0c;具体方法是“守破离”。反复练习直到熟练。————百战程序员1.0 XML1.1 XML 简介XML 指可扩展标记语言。XML 被设计用来传输和存储数据。1. 什么是XMLXML 指可扩展标记语言&#xff08;EXten…

WebDriver API元素的定位

一、以下截图为用FireBug定位的用火狐(Firefox)浏览器打开的百度首页&#xff0c;下面所讲述的八种定位方法&#xff0c;就是以该截图中的百度输入框为例子。 ①、FireBug是Firefox浏览器下的开发类插件&#xff0c;通过该插件可以查看HTML、CSS、Javascript控制台、网络状况监…

findbugs-dea_FindBugs和JSR-305

findbugs-dea假设该组开发人员在大型项目的各个部分上并行工作-一些开发人员在进行服务实现&#xff0c;而其他开发人员在使用该服务的代码。 考虑到API的假设&#xff0c;两个小组都同意服务API&#xff0c;并开始单独工作。 您认为这个故事会有幸福的结局吗&#xff1f; 好吧…

带有ActiveMQ和Maven的JMS Sender应用程序

我们已经看到了如何使用ActiveMQ和Maven创建JMS Receiver应用程序 。 让我们看看我们如何类似地创建JMS Sender应用程序 。 web.xml与创建接收器应用程序时使用的相同&#xff1a; <web-app xmlns"http://java.sun.com/xml/ns/javaee"xmlns:xsi"http://www…

mysql aes密钥大于16位_aes秘钥限制问题解决办法

在oarcle jdk1.8上执行256位的aes秘钥加密报错如下:java.lang.RuntimeException: java.security.InvalidKeyException: Illegal key sizeat com.xx.opal.core.utils.aes.AESTool.encryptWithoutEncode(AESTool.java:33)at com.xx.opal.aes.AESTest.test(AESTest.java:19)at sun…

background-clip与background-origin

规定背景的绘制区域 浏览器支持 IE9、Firefox、Opera、Chrome 以及 Safari 支持 background-clip 属性。 注释&#xff1a;Internet Explorer 8 以及更早的版本不支持 background-clip 属性。IE9、Firefox、Opera、Chrome 以及 Safari 支持 background-clip 属性。 有三个值&am…

策略模式应用场景和uml_策略模式

策略模式应用场景和uml在最近的博客中&#xff0c;我收到了Wojciech Soczy&#xff1f;ski的评论&#xff0c;内容涉及在使用“不要问”&#xff08;TDA&#xff09;时如何使用“战略”模式实施单一责任原则&#xff08;SRP&#xff09;。 在某些时候&#xff0c;我打算进一步讨…

mysql建表时主键_mysql建表时怎么设置主键?

设置方法&#xff1a;在“CREATE TABLE”语句中&#xff0c;通过“PRIMARY KEY”关键字来指定主键&#xff0c;语法格式“字段名 数据类型 PRIMARY KEY [默认值]”或“[CONSTRAINT 约束名] PRIMARY KEY 字段名”。主键(PRIMARY KEY)的完整称呼是“主键约束”&#xff0c;是 MyS…

在OpenShift上部署Java EE微服务

我昨天用WildFly Swarm在博客上发布了有关简单JAX-RS微服务的博客。 您学习了如何使用Maven构建一个所谓的“胖子”&#xff0c;还使用Maven Docker插件对我们的微服务进行了Docker化并在Docker Machine上本地运行。 这是在本地测试事物的好方法。 到目前为止&#xff0c;缺少的…