Demo背景
实现类似于gwt框架的功能,通过java代码来编写界面组件,在将界面组件转换成浏览器可识别的UI元素
设计思路:
代码要实现两部分功能:
1.编写界面组件代码,用java类定义出所需要的界面元素(Button、Label、Panel等)
2.将java类组件进行语义转换,转换成界面引擎可识别的语法(json、html,js等)
接口设计:
界面组件的设计参考awt采用组合模式进行封装
Element是所有类组件的接口,包括单一组件(Button、Label)和容器组件Container
语义转换功能接口为Render
参观者模式使用:
Element和Render是两个相互独立的组件,它们各自封装着自己的功能,现两个组件需要交互,Render需要访问Element来获取其封装的信息
首先在Element中声明accept方法用来表示自身接受Render的访问
public interface Element {
public void acceptRender(Render render);
}
然后在Render类中声明visit方法用来参观Element
public interface Render {
public void visitElement(Element elt);
}
visitElement方法的执行可通过Element的acceptRender方法来触发
public abstract class AbstractElement implements Element {
public void acceptRender(Render render) {
render.visitElement(this);
}
}
这样,在执行Element.acceptRender(render)方法时,render便可以引用到Element对象以完成组件交互的逻辑,从而避免了通过类构造参数来封装彼此的弊端
组合模式使用:
组合模式针对单体实体和集合实体设计了相同的接口,接口实现类中,集合实体需要遍历其子集,调用子集的方法来完成相同的处理。从而将主程序的递归逻辑转移到集合实体中去完成。
这里面的集合实体为Container,它和其他单体实体(Button、Label)一样继承至Element
其acceptRender方法实现逻辑如下:
public void acceptRender(Render render) {
render.visitElement(this);//首先通过参观者模式处理自身
for(Element child:children){//处理其封装的子集
Render childRender=RenderFactory.getRender(child.getClass().getName());
//子集可能是单体实体,也可能是集合实体,调用子集相同的方法来完成递归处理
child.acceptRender(childRender,jg);
}
}
而单体实体的处理逻辑如下:
public void acceptRender(Render render) {
render.visitElement(this,jg);//只需要处理自身便可
}
这样当集合实体所遍历的子集类型为单体实体时则不再向下递归