从避免重复到设计模式

避免重复是为了使相同或相似的代码不再重复出现,
相同的代码很容易发现并且被复用,但相似的代码
不那么容易发现并且被复用。如果只是几个参数有
变化,可以通过传参的方法。但如果像下面的例子,
怎么分离变和不变的呢?
class Invoice...
String asciiStatement() {
StringBuffer result = new StringBuffer();
result.append(“Bill for “ + customer + “\n”);
Iterator it = items.iterator();
while(it.hasNext()) {
LineItem each = (LineItem) it.next();
result.append(“\t” + each.product() + “\t\t”
+ each.amount() + “\n”);
}
result.append(“total owed:” + total + “\n”);
return result.toString();
}

String htmlStatement() {
StringBuffer result = new StringBuffer();
result.append(“<P>Bill for <I>” + customer + “</I></P>”);
result.append(“<table>”);
Iterator it = items.iterator();
while(it.hasNext()) {
LineItem each = (LineItem) it.next();
result.append(“<tr><td>” + each.product()
+ “</td><td>” + each.amount() + “</td></tr>”);
}
result.append(“</table>”);
result.append(“<P> total owed:<B>” + total + “</B></P>”);
return result.toString();
}
这里要完成显示ascii和html两种形式的表达式。
两种情况下,都有如下的结构(不变的东西):
1.打印一个页头。
2.遍历所有item,并打印出来。
3.打印一个页脚。
所以可以抽象出以下一个接口:
interface Printer {
String header(Invoice iv);
String item(LineItem line);
String footer(Invoice iv);
}
和一个实现这个接口的类:
static class AsciiPrinter implements Printer {
public String header(Invoice iv) {
return “Bill for “ + iv.customer + “\n”;
}
public String item(LineItem line) {
return “\t” + line.product()+ “\t\t” + line.amount() +“\n”;
}
public String footer(Invoice iv) {
return “total owed:” + iv.total + “\n”;
}
}
客户端代码如下:
class Invoice...
public String statement(Printer pr) {
StringBuffer result = new StringBuffer();
result.append(pr.header(this));
Iterator it = items.iterator();
while(it.hasNext()) {
LineItem each = (LineItem) it.next();
result.append(pr.item(each));
}
result.append(pr.footer(this));
return result.toString();
}

class Invoice...
public String asciiStatement2() {
return statement (new AsciiPrinter());
}

熟悉设计模式的朋友可能会发现这就是Template method。
所以如果你坚决要在一个地方使用设计模式,一定要问自己
:“这里我消除了什么代码重复?”。如果答案是没有任何
代码重复被消除,那么就不要用设计模式。

怎么没人回我?

你这其实是refactory的宗旨,当你第三次发现重复时,你就要着手重整了。