Groovy探索之Builder 三
因为我们知道builder模式是从使用
MarkupBuilder开始的,而
MarkupBuilder是生成xml文件的。很自然的,当我想做第一个自己的builder的时候,我就会做一个table的builder。用来生成如下的代码:
<tr>
<td>Name</td>
<td>Age</td>
<td>Address</td>
</tr>
<tr>
<td>tom</td>
<td>33</td>
<td>Shenzhen</td>
</tr>
<tr>
<td>mike</td>
<td>22</td>
<td>Taibei</td>
</tr>
builder.
td
'Name'
而如果是下面的代码:
<td colspan=”4”>Name</td>
这样的代码,在创建的时候,肯定是这样写:
builder.
td([rowspan:
'4'
],
'Name'
)
protected
Object createNode(Object name,Object value){
sb<<
"<"
sb<<name.toString()
sb<<
">"
sb<<value.toString()
sb<<
"</"
sb<<name.toString()
sb<<
">"
}
protected
Object createNode(Object name){
sb<<
"<"
sb<<name.toString()
sb<<
">"
sb<<
"</"
sb<<name.toString()
sb<<
">"
}
<tr></tr>
分析到了这里,才找到了我们实现整个业务需求的难点所在。如何解决这个问题呢?答案就是
BuilderSupport
的“
nodeCompleted(Object parent,Object node)
”方法。
下面我们来看看整个类是如何实现的:
class
HtmlTrBuilder
extends
BuilderSupport {
private
StringBuffer sb =
new
StringBuffer();
def
isTd =
true
;
protected
void
setParent(Object parent,Object child){
}
protected
Object createNode(Object name){
sb<<
"<"
<<name.toString()<<
">"
if
(name.toString().toLowerCase() ==
'td'
)
{
sb<<
"</"
<<name.toString()<<
">"
isTd =
true
}
}
protected
void
nodeCompleted(Object parent,Object node) {
if
(!
this
.isTd)
{
this
.sb<<
'</tr>'
}
else
{
this
.isTd =
false
;
}
}
看到这个方法,我们就明白了为什么要置
isTd
为“
true
”,因为如果
isTd
为“
false
”的话,在“
nodeCompleted
”方法里就要执行“
this
.sb<<
'</tr>'
”,也就是关闭了“
tr
”标签。
同样的道理,下面的这三个方法就不难理解了:
protected
Object createNode(Object name,Object value){
sb<<
"<"
sb<<name.toString()
sb<<
">"
sb<<value.toString()
if
(name.toString().toLowerCase() ==
'td'
)
{
sb<<
"</"
<<name.toString()<<
">"
isTd =
true
}
}
protected
Object createNode(Object name,Map attributes){
sb<<
"<"
sb<<name.toString()
sb<<
" "
attr.
each
{
it ->
sb<<it.key.toString()
sb<<
"=/""
sb<<it.value.toString()
sb<<
"/""
}
sb<<
">"
if
(name.toString().toLowerCase() ==
'td'
)
{
sb<<
"</"
<<name.toString()<<
">"
isTd =
true
}
}
protected
Object createNode(Object name,Object value){
sb<<
"<"
sb<<name.toString()
sb<<
" "
attr.
each
{
it ->
sb<<it.key.toString()
sb<<
"=/""
sb<<it.value.toString()
sb<<
"/""
}
sb<<
">"
sb.
append
(value.toString())
if
(name.toString().toLowerCase() ==
'td'
)
{
sb<<
"</"
<<name.toString()<<
">"
isTd =
true
}
}
}
class
HtmlTrBuilder
extends
BuilderSupport {
private
StringBuffer sb =
new
StringBuffer();
def
isTd =
true
;
def
makeWithAttr = {
name,attr ->
sb<<
"<"
sb<<name.toString()
sb<<
" "
attr.
each
{
it ->
sb<<it.key.toString()
sb<<
"=/""
sb<<it.value.toString()
sb<<
"/""
}
sb<<
">"
}
def
doTdEnd = {
name ->
if
(name.toString().toLowerCase() ==
'td'
)
{
sb<<
"</"
<<name.toString()<<
">"
isTd =
true
}
}
protected
void
setParent(Object parent,Object child){
}
protected
Object createNode(Object name){
sb<<
"<"
<<name.toString()<<
">"
doTdEnd.
call
(name)
}
protected
Object createNode(Object name,Object value){
sb<<
"<"
sb<<name.toString()
sb<<
">"
sb<<value.toString()
doTdEnd.
call
(name)
}
protected
Object createNode(Object name,Map attributes){
makeWithAttr.
call
(name,attributes)
doTdEnd.
call
(name)
}
protected
Object createNode(Object name,Object value){
makeWithAttr.
call
(name,attributes)
sb.
append
(value.toString())
doTdEnd.
call
(name)
}
protected
void
nodeCompleted(Object parent,Object node) {
if
(!
this
.isTd)
{
this
.sb<<
'</tr>'
}
else
{
this
.isTd =
false
;
}
}
}
最后,我们来对上面的代码进行测试:
HtmlTrBuilder htb =
new
HtmlTrBuilder()
htb.tr
{
td([rowspan:
'2'
],
'a'
)
td([colspan:
'3'
],
'b'
)
td
'c'
td
'd'
td
'e'
td([rowspan:
'3'
],
'f'
)
}
htb.tr
{
td([colspan:
'2'
],
'g'
)
td
'h'
td
'i'
td
'j'
td
'k'
}
htb.tr
{
td
'l'
td
'm'
td
'n'
td
'o'
td
'p'
td
'q'
td
'r'
}
println
htb.sb.toString()
运行结果为:
<tr><td rowspan="2">a</td><td colspan="3">b</td><td>c</td><td>d</td><td>e</td><td rowspan="3">f</td></tr><tr><td colspan="2">g</td><td>h</td><td>i</td><td>j</td><td>k</td></tr><tr><td>l</td><td>m</td><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td></tr>
原文地址:https://www.jb51.cc/groovy/843021.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。