`

基于Java的界面布局DSL的设计与实现(续)

    博客分类:
  • Java
阅读更多

  界面布局语言设计与实现

  在本小节中,我们会对上面介绍的界面布局语言的一些设计和实现细节进行介绍。我们这里所讲解的是基于 Java Swing 的实现。读者可以根据自己的需要在其他的语言和界面开发工具包上去实现该界面布局语言。

  界面布局语言的主要设计思路有两点:

   在接口中遵循《Domain Driven Desing》作者 Eric Evans 提出的 FluentInterface 的概念;
   语言的层次化设计。

  界面布局语言所提供的接口不是 Java 语言层面上的对象接口,也不是使用基于 Java 的语法来使用这些接口构建复杂的界面。相反,我们提供了一个面向界面设计规格描述的接口,接口的语义、规则以及命名完全和界面设计中的规则、概念相符,这样就可以直接使用代码来清晰、直接地表达出界面设计中的布局概念。

  在界面布局语言的设计上,我们没有采用定制的面向对象的设计,而是由一组处于不同层次的语言组成,每个层次都是通过对该层的基本原子进行组合构造而来,每个层次所构造出来的实体,则可以作为上一层语言的基本原子使用。这样,我们就在通用的 Java 语言之上,逐步构建出了一种专用于表达界面布局的语言。比起传统的对象设计,这种方法具有更高的抽象层次和通用性。

  我们来看一下界面布局语言中基本原子的实现细节,先来看一下 Component 的定义:

public interface Component {
public Component at(int x, int y, int width, int height); 
public Component in(Container); 
……
}

  Button 的实现如下:

public class Button implements Component{
public JButton btn = new JButton(); 
public Component title(String t){
btn.setText(t); 
return this; 
}
public Component at(int x, int y, int width, int height) {
Rectangle rect = new Rectangle(x,y,width,height); 
btn.setBounds(rect); 
return this; 
}
public Component in(Container parent){
parent.add(btn); 
return this; 
}
……
}

  从上面的代码中,读者会发现这种写法和传统的 API 写法风格的不同。在这种风格中,为了能够将调用形成一个句子,每个调用在结束时都返回了 this。另外,在给方法起名时也有不同的考虑,不只是关注于该方法的职责和功能,而是更关注于该方法名在整个句子这个上下文中是否通顺、是否更富表达力。

  随着更多基本原子组件的编写,会发现 in 和 at 方法在很多组件中都重复出现,此时可以把它们提取到一个抽象基类中。这里这样写是为了清楚起见。

  下面我们来看看 Empty 组件,beside 和 above 组合子的实现方法,它们都很简单。

public class Empty implements Component {
public Component at(int x,int y,int width,int height) {
return this; 
}
public Component in(Container {
return this; 
}
}

  Empty 只是起到了一个布局空间占位的作用。beside 和 above 的实现如下:

public class beside implements Component {
private Component left,right; 
private float ratio; 
public beside(Component left,Component right,float ratio){
this.left = left; 
this.right = right; 
this.ratio = ratio; 
}
public Component at(int x,int y,int width,int height) { 
left.at(x, y, width*ratio,height); 
right.at(x+ width*ratio, y, width*(1-ratio),height); 
return this; 
}
public Component in(Container parent) {
left.in(parent); 
right.in (parent); 
return this; 
}
……
}
public class above implements Component {
private Component up,low; 
private float ratio; 
public above(Component up, Component low, float ratio){
this.up = up; 
this.low = low; 
this.ratio = ratio; 
}
public Component at(int x,int y,int width,int height) { 
up.at(x, y, width,height*ratio); 
low.at(x, y+height*ratio, width,height*(1-ratio)); 
return this; 
}
public Component in(Container parent) {
up.in(parent); 
low.in (parent); 
return this; 
}
……
}

  为了保证组合操作的闭包性质,这两个组合子都实现了 Component 接口,并且把组合的结果当作一个 Component 返回。这两个组合子的主要功能就是把给定的布局空间按照指定的比例进行分隔,并把给定的组件放到分隔好的布局空间中去。其中的算法比较简单,就不再赘述。

  基于这些基本的原子元素和组合子,就可以构建出任意复杂程度的布局样式。在前面语言介绍小节中,我们给出了一些如:center、h_seq、v_seq、block 以及 block_with_margin 等简单布局样式的实现。读者可以根据自己的需要定义并积累自己的布局样式库。

  前面提到过,我们的界面布局语??敮?楆敬搨捯????????言是分层的,大家可以看出,在最底层是我们的 Java Swing 界面开发语言,我们在其上构建出了界面布局位置描述语言,使用该布局位置描述语言中的组合子:beside 和 above,我们在其上又构建出了用来定义和表达各种布局样式的布局样式描述语言。 

  敏锐的读者会发现,在前面讲述的界面布局语言中仅仅涉及了界面布局元素的显示样式方面的内容,但是一个完整的界面是需要和后端的应用逻辑交互的,因此还需要一个粘合界面显示和应用模型的层次。

  确实是这样的,我们在这里之所以没有提这项内容主要是为了避免陷入其实现的琐碎细节中,从而可以集中介绍界面布局语言本身。为了能够对界面布局元素进行编程控制,我们让每个布局元素都有一个“拥有者”。和布局元素在物理上的包含关系不同,“拥有者”是编程语义上的。也就是说,对布局元素在编程意义上的所有控制操作都在其“拥有者”中完成,这种思路完全隔离了显示和控制,其实就是 MVP 模式的一种实现。

  比如,我们可以这样描述一个 Button:

Button().title(“button1”).ownby(btn1Controller);

  关于 Button 的所有事件处理和操控都在 btn1Controller 中完成。有机会的话,我们会在后续的文章中对此进行详细的介绍,现在我们将其实现作为一个练习留给读者来完成。

  关于设计的几点思考

  在本文中,我们介绍了一种界面布局语言以及它的设计和实现。在此,我们有必要对其中的设计思路进行一个回顾。

  在设计中,我们没有采用对象技术中常用的一些设计手段,我们没有对界面布局本身进行抽象,也不是设计出一些特定的界面布局管理器。相反,我们把对象技术当成一种低层的抽象工具,并基于它来构建更高层次的抽象,创建出更加接近我们所工作的问题领域的语言,从而获得更高的生产力、表达力以及可重用性(还有什么比语言更加易于重用),这就是目前探讨的比较热烈的面向语言编程(Language-Oriented Programming)。

  前面已经介绍过,我们的界面布局语言是分层的,这种设计非常有助于构建健壮的程序。这里健壮的含意是指:问题领域中的一个小的更改,所导致的程序更改也应当是相应地小的。比如,我们在构建迷你计算器时,希望所有数字以及运算符按钮都在横向和纵向留一些空白,这个问题领域中的一个小的更改,所对应的程序更改就是把 block 更改为 block_with_margine 而已。此外,由于分层的存在,我们可以自由地修改不同层次的表达细节而对其他层次不会造成任何影响。也就是说,每一层提供了用于表达系统特征的不同词汇以及不同的更改方式和能力。

  由于动态语言提供了更高的动态性和元编程能力,因此在动态语言中更容易实现这种设计思路,我们也用 Python 语言基于 wxPython 界面工具库实现了本文中讲解的界面布局语言,相比 Java,它的实现确实要容易和清晰地多。

分享到:
评论

相关推荐

    利用 Java 实现组合式解析器,基于 Java 的界面布局 DSL 的设计与实现(转载)

    4. **DSL 设计**:如何定义一个简洁、直观的界面布局DSL,包括关键字选择、语法规则制定等。 5. **Java 内部 DSL**:如何利用 Java 的类、接口和方法来构造内部DSL,让代码更易读、易维护。 6. **解析库的使用**:...

    基于Java的界面布局DSL的设计与实现

    界面布局语言介绍界面布局语言设计与实现关于设计的几点思考参考资料界面设计应该是一项充满创造性、富有乐趣的工作,但是却往往被认为非常的枯燥和繁琐。究其原因,是因为界面布局领域所采用的描述概念和具体的实现...

    基于Java的订餐系统安卓设计源码

    本项目是一个基于Java技术开发的安卓订餐系统源码,主要功能是为餐饮行业提供一个便捷的在线订餐和订单管理平台。以下是该系统的一些关键知识点: 1. **Java编程语言**:整个系统的核心编程语言是Java,这是一种...

    JAVA上百实例源码以及开源项目源代码

    例如,容易实现协议的设计。 Java EJB中有、无状态SessionBean的两个例子 两个例子,无状态SessionBean可会话Bean必须实现SessionBean,获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,计算利息等;在...

    Android-一个简洁的汇率转换软件使用kotlin编写

    本项目是一个基于Kotlin的简洁汇率转换应用,它利用了Anko库来简化UI创建,并实现了主题的动态切换效果,为用户提供更优质的交互体验。 首先,我们来了解Kotlin的基础知识。Kotlin是JetBrains公司开发的一种静态...

    groovy-jmx-dsl:用于基于 Swing 的 JMX 仪表板的 Groovy DSL

    2. 示例:可能包含了一些预设的 Groovy 脚本,展示如何使用 DSL 来定义界面布局和连接到 JMX 服务器。 3. 文档:可能有项目文档,解释如何安装、配置和使用 Groovy-JMX-DSL。 4. 测试:可能包含了测试用例,帮助验证...

    java学习笔记4

    9. **JavaFX或Swing**:如果涉及到图形用户界面(GUI)开发,那么JavaFX或Swing可能是讨论的内容,包括组件的使用、布局管理、事件处理等。 10. **Spring框架**:如果笔记内容深入到企业级开发,那么Spring框架的...

    Android-用kotlin实现的纯粹倒计时应用

    本项目是一个基于Kotlin实现的纯粹倒计时应用,它提供了基础的倒计时功能,帮助用户跟踪时间,比如用于设定目标、提醒事件或者简单的计时任务。以下是关于这个项目的一些关键知识点和实现细节: **1. Kotlin基础** ...

    dsl-maker:Kotlin多平台库,可帮助使用ANTLR或简单的内置解析器创建DSL

    - **UI描述**:定义用户界面布局,使得非程序员也能参与到UI设计中。 - **测试脚本**:创建简洁的测试语言,方便编写测试用例。 在“dsl-maker-main”这个压缩包中,很可能是包含了DSL-maker库的源码,通过查看和...

    Kotlin的轻量级JavaFX框架

    在Java开发领域,GUI图形用户界面的设计与实现是不可或缺的一部分。JavaFX提供了一种强大的工具集,用于创建桌面应用的富客户端界面。而当Kotlin与JavaFX结合时,我们可以得到一个更加简洁、易读且高效的开发体验。...

    无线智能表数据采集与管理系统(客户端)软件设计.zip

    在UI设计中,Kotlin的Anko库提供了简化XML布局的DSL(领域特定语言),使开发者能更直观地构建用户界面。此外,Kotlin的可空性检查和扩展函数特性,有助于创建更加健壮的UI组件。 数据处理是系统的核心部分。在无线...

    2022年广州大学拟定题目-202111201

    【基于Java Web的在线考试系统】 Java Web技术用于构建分布式、跨平台的网络应用,本课题旨在构建一个在线考试系统,包含如下功能: 1. 学生模块:参加考试、修改个人信息、查看成绩。 2. 教师模块:维护试题、...

    Grails_Portal.pdf

    - 设计和实现门户布局及功能。 - 集成外部服务和数据源。 - 测试和部署门户应用。 #### Grails Portal未来展望 - **发展方向**:Grails Portal框架未来的发展方向可能包括增强安全性、提高性能、增加更多高级...

    自己编写的100个javacc例子程序

    `GUIParsing`可能涉及到解析与图形用户界面相关的语法,比如XML布局文件。`JJTreeExamples`则可能是一系列使用JavaCC的扩展工具JJTree创建的语法树示例,JJTree可以将解析树转换为抽象语法树(AST),方便进行进一步...

    android-java

    3. **布局**:XML文件用于定义用户界面的布局,但Java代码可以动态地创建和修改布局。例如,你可以根据用户行为或数据状态动态添加或移除View。 4. **数据存储**:Android提供多种数据存储方式,如SQLite数据库、...

    GEF原理的详细介绍+程序实例和程序源码

    EMF基于Java对象模型,可以生成模型的XML序列化、持久化支持以及相应的Java类,使得数据模型能够方便地被读取、存储和交换。 **GEF原理** 主要包括以下几个关键部分: 1. **模型(Model)**:这是GEF应用程序的基础...

    Android项目影视评价项目文档

    2. `java`目录存放Java源代码和测试代码,是实现业务逻辑的核心部分。 3. `res`资源目录则包含了各种项目资源: - `drawable`用于存储图片资源。 - `layout`存放XML布局文件,定义用户界面。`activity_main.xml`...

    eclipse-scout-2023-09-R-win32-x86-64.zip

    Eclipse Scout 是一个开源的企业级应用开发框架,主要用于构建基于Java和HTML5的桌面和Web应用程序。这个压缩包“eclipse-scout-2023-09-R-win32-x86-64.zip”包含了针对Windows 64位系统的Eclipse Scout的最新版本...

    android-studio-ide-202.7486908-mac

    4. **布局设计器**: 提供视觉化的界面布局编辑器,可实时预览UI在不同设备上的效果,并支持拖放组件,简化UI设计。 5. **调试工具**: 内置强大的调试器,支持单步执行、设置断点、查看变量值、性能分析等功能,帮助...

Global site tag (gtag.js) - Google Analytics