在日常开发过程中,我们常常会接到这样的需求:其中很多功能的内部逻辑大致相似,仅仅是部分处理有区别。面对这样的需求,我们在编码过程中经常会编写大量重复的模板代码,又或者采取的做法是写很多判断条件从而将一个方法写的非常“臃肿”。
例如下面这个需求,对JavaBean对象进行不同格式的数据包装,同时操作前后要进行日志打印。也许你会这样编写代码:
public class Formatter {
public static final int XML = 0;
public static final int JSON = 1;
public String formatBook(Book book, int format) {
System.out.println("format begins");
String result = "";
if (format == XML) {
result += "<book_name>" + book.getBookName() + "</book_name>\n";
result += "<pages>" + book.getPages() + "</pages>\n";
result += "<price>" + book.getPrice() + "</price>\n";
result += "<author>" + book.getAuthor() + "</author>\n";
result += "<isbn>" + book.getIsbn() + "</isbn>\n";
} else if (format == JSON) {
result += "{\n";
result += "\"book_name\" : \"" + book.getBookName() + "\",\n";
result += "\"pages\" : \"" + book.getPages() + "\",\n";
result += "\"price\" : \"" + book.getPrice() + "\",\n";
result += "\"author\" : \"" + book.getAuthor() + "\",\n";
result += "\"isbn\" : \"" + book.getIsbn() + "\",\n";
result += "}";
}
System.out.println("format finished");
return result;
}
}
public class Test {
public static void main(String[] args) throws Exception {
Book book = new Book();
book.setBookName("Thinking in Java");
book.setPages(880);
book.setPrice(68);
book.setAuthor("Bruce Eckel");
book.setIsbn("9787111213826");
Formatter formatter = new Formatter();
String result = formatter.formatBook(book, Formatter.XML);
System.out.println(result);
result = formatter.formatBook(book, Formatter.JSON);
System.out.println(result);
}
}
当然,这样做可以满足要求,但是会有一个问题。那就是它的可扩展性比较差,如果我们想要再增加一种格式类型,就要再写一个 if 判断条件。如果长此下去,不断的增加判断条件,那么这段代码便会变得“不堪入目”。
为了改进这种情况,我们可以采用模板方法模式。这种模式具有很强的可扩展性,特别适合这种不断增加判断条件的需求。来看一下它的定义。
模板方法(Template Method)模式: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
下面就用模板方法模式来改进这段代码。
首先定义一个抽象类,将处理公共逻辑的方法(骨架)写成公有方法,以供调用;而将处理具体逻辑的方法写成抽象方法,以供扩展。
public abstract class Formatter {
public String formatBook(Book book, int format) {
beforeFormat();
String result = formating(book);
afterFormat();
return result;
}
protected void beforeFormat() {
System.out.println("format begins");
}
protected abstract String formating(Book book);
protected void afterFormat() {
System.out.println("format finished");
}
}
接下来,我们只要定义专门的子类来处理具体逻辑即可。
public class XMLFormatter extends Formatter {
@Override
protected String formating(Book book) {
String result = "";
result += "<book_name>" + book.getBookName() + "</book_name>\n";
result += "<pages>" + book.getPages() + "</pages>\n";
result += "<price>" + book.getPrice() + "</price>\n";
result += "<author>" + book.getAuthor() + "</author>\n";
result += "<isbn>" + book.getIsbn() + "</isbn>\n";
return result;
}
}
public class JSONFormatter extends Formatter {
@Override
protected String formating(Book book) {
String result = "";
result += "{\n";
result += "\"book_name\" : \"" + book.getBookName() + "\",\n";
result += "\"pages\" : \"" + book.getPages() + "\",\n";
result += "\"price\" : \"" + book.getPrice() + "\",\n";
result += "\"author\" : \"" + book.getAuthor() + "\",\n";
result += "\"isbn\" : \"" + book.getIsbn() + "\",\n";
result += "}";
return result;
}
}
最后调用代码如下:
public class Test {
public static void main(String[] args) throws Exception {
Book book = new Book();
book.setBookName("Thinking in Java");
book.setPages(880);
book.setPrice(68);
book.setAuthor("Bruce Eckel");
book.setIsbn("9787111213826");
XMLFormatter xmlFormatter = new XMLFormatter();
String result = xmlFormatter.formatBook(book);
System.out.println(result);
JSONFormatter jsonFormatter = new JSONFormatter();
result = jsonFormatter.formatBook(book);
System.out.println(result);
}
}
通过模板方法模式的改写,是不是发现这段代码变得“清爽”了许多呢?快将这种设计模式应用到你的日常开发中吧,相信它一定会对你大有帮助。
扫描二维码关注公众号,回复:
8768724 查看本文章