界面布局语言设计与实现
在本小节中,我们会对上面介绍的界面布局语言的一些设计和实现细节进行介绍。我们这里所讲解的是基于 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); …… } |
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; } …… } |
public class Empty implements Component { public Component at(int x,int y,int width,int height) { return this; } public Component in(Container { return this; } } |
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; } …… } |
Button().title(“button1”).ownby(btn1Controller); |