| 从上面的代码中,读者会发现这种写法和传统的 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)。 上一页 [1] [2] [3] [4] 下一页
 【责编:Luzi】 |