对于可以获取String并输出HTML的小型系统,哪种设计模式适合?
这是一个小例子:
public String makeStrong(String in) {
return "<strong>" + in + "</strong>";
}
当然,它需要对某些层次结构进行建模,以使其适合<ul>
和<ol>
及其子项。我想的是装饰器,但复合模式听起来也不错。我应该考虑什么?
答案 0 :(得分:3)
考虑用于构建经过验证的HTML片段的构建器模式。我写了一些类似于验证HTML的内容,以便在Swing应用程序组件中使用,例如提示。以下是您可以构建的粗略骨架:
public final class HtmlBuilder()
{
private final StringBuilder sb = new StringBuilder();
private final Deque tagStack = new ArrayDeque();
public HtmlBuilder()
{
startTag("html");
}
// Consider using an enum of valid tags and extending to support attributes
public HtmlBuilder startTag( String tag )
{
// TODO preconditions
tagStack.push( tag );
sb.append('<').append(tag).append('>');
return this;
}
public HtmlBuilder endTag( String tag )
{
// TODO preconditions,
// e.g. check "!tagStack.isEmpty() && tagStack.peek().equals( tag )
tagStack.pop();
sb.append('<').append('/').append(tag).append('>');
return this;
}
public HtmlBuilder append( String text )
{
// TODO Preconditions, check for/escape special characters etc
sb.append( text );
return this;
}
@Override
public String toString()
{
endTag("html")
return sb.toString();
}
}
简单用例:
String html = new HtmlBuilder()
.startTag( "strong" ).append( "text" ).endTag( "strong" )
.toString();
您可以根据需要添加尽可能多的验证,例如将“tr”定义为仅允许在“表”中。我怀疑那里已经存在这样的事情了。
答案 1 :(得分:2)
乍一看,我想到了一个Builder模式或更好的流畅API。 以下更紧凑:
import static a.b.c.HTML.*;
String html = p(
ol(
li(),
li(
_("Hello, "),
strong(_("World")),
_("!")
),
li()
)
).toString();
public class HTML {
protected final String tag;
private final HTML[] items;
public HTML(String tag, final HTML... items) {
this.tag = tag;
this.items = items;
}
public static HTML _(String text) {
return new HTML(text) {
@Override
public String toString() {
return tag;
}
@Override
protected void buildString(StringBuilder sb) {
sb.append(tag);
}
};
}
public static HTML li(final HTML... items) {
return new HTML("li", items);
}
public static HTML ol(final HTML... items) {
return new HTML("ol", items);
}
public static HTML p(final HTML... items) {
return new HTML("p", items);
}
public static HTML strong(final HTML... items) {
return new HTML("strong", items);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
buildString(sb);
return sb.toString();
}
protected void buildString(StringBuilder sb) {
sb.append('<').append(tag);
if (items.length == 0) {
sb.append(" />");
} else {
sb.append('>');
for (HTML item : items) {
item.buildString(sb);
}
sb.append("</").append(tag).append('>');
}
}
}
答案 2 :(得分:2)
使用AutoCloseable
界面的简约方法如下:
程序打印
<body><strong> some text </strong><ol><li>a</li><li>b</li><li>c</li></ol></body>
Online demo
public class Main {
public static void main(String args[]) {
Page page = new Page();
writeBody(page);
page.show();
}
static void writeBody(Page page) {
try (BodyTag bodyTag = new BodyTag(page)) {
writeText(page);
writeList(page);
}
}
static void writeText(Page page) {
try (StrongTag strongTag = new StrongTag(page)) {
strongTag.append(" some text ");
}
}
static void writeList(Page page) {
try (ListTag list = new ListTag(page)) {
// A twisted way to write a, b and c as elements
for (char c=97; c<100; ++c) {
appendElem(page, String.valueOf(c));
}
}
}
static void appendElem(Page page, String elem) {
try (ListElem li = new ListElem(page)) {
li.append(elem);
}
}
}
class Page {
StringBuilder content = new StringBuilder();
void append(String text) {
content.append(text);
}
void show() {
System.out.println(content);
}
}
abstract class Tag implements AutoCloseable {
String name;
Page content;
Tag(Page parent, String tagName) {
name = tagName;
content = parent;
content.append("<");
content.append(name);
content.append(">");
}
public void append(String text) {
content.append(text);
}
@Override
final public void close() {
content.append("</");
content.append(name);
content.append(">");
}
}
final class StrongTag extends Tag {
public StrongTag(Page parent) {
super(parent, "strong");
}
}
final class BodyTag extends Tag {
public BodyTag(Page parent) {
super(parent, "body");
}
}
final class ListTag extends Tag {
public ListTag(Page parent) {
super(parent, "ol");
}
}
final class ListElem extends Tag {
public ListElem(Page parent) {
super(parent, "li");
}
}
绝对不是白痴,但对于简单的用途,它可能是一个良好的开端。