转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8744002

今天你还是像往常一样来上班,一如既往地开始了你的编程工作。

项目经理告诉你,今天想在服务器端增加一个新功能,希望写一个方法,能对Book对象进行处理,将Book对象的所有字段以XML格式进行包装,这样以后可以方便与客户端进行交互。并且在包装开始前和结束后要打印日志,这样方便调试和问题定位。

没问题!你觉得这个功能简直是小菜一碟,非常自信地开始写起代码。

Book对象代码如下:

  1. public class Book {
  2. private String bookName;
  3. private int pages;
  4. private double price;
  5. private String author;
  6. private String isbn;
  7. public String getBookName() {
  8. return bookName;
  9. }
  10. public void setBookName(String bookName) {
  11. this.bookName = bookName;
  12. }
  13. public int getPages() {
  14. return pages;
  15. }
  16. public void setPages(int pages) {
  17. this.pages = pages;
  18. }
  19. public double getPrice() {
  20. return price;
  21. }
  22. public void setPrice(double price) {
  23. this.price = price;
  24. }
  25. public String getAuthor() {
  26. return author;
  27. }
  28. public void setAuthor(String author) {
  29. this.author = author;
  30. }
  31. public String getIsbn() {
  32. return isbn;
  33. }
  34. public void setIsbn(String isbn) {
  35. this.isbn = isbn;
  36. }
  37. }

然后写一个类专门用于将Book对象包装成XML格式:

  1. public class Formatter {
  2. public String formatBook(Book book) {
  3. System.out.println("format begins");
  4. String result = "";
  5. result += "<book_name>" + book.getBookName() + "</book_name>\n";
  6. result += "<pages>" + book.getPages() + "</pages>\n";
  7. result += "<price>" + book.getPrice() + "</price>\n";
  8. result += "<author>" + book.getAuthor() + "</author>\n";
  9. result += "<isbn>" + book.getIsbn() + "</isbn>\n";
  10. System.out.println("format finished");
  11. return result;
  12. }
  13. }

调用代码如下:

  1. public class Test {
  2. public static void main(String[] args) throws Exception {
  3. Book book = new Book();
  4. book.setBookName("Thinking in Java");
  5. book.setPages(880);
  6. book.setPrice(68);
  7. book.setAuthor("Bruce Eckel");
  8. book.setIsbn("9787111213826");
  9. Formatter formatter = new Formatter();
  10. String result = formatter.formatBook(book);
  11. System.out.println(result);
  12. }
  13. }

你写好了之后,迫不及待地开始运行,运行结果也完全符合你的期望。

项目经理看完后,对你非常满意,小伙效率很高的嘛!你也非常的得意。

不过两天之后,项目经理又找到了你,他说之前没有考虑到需要交互的客户端还包括手机设备,而手机设备都比较吃流量,用XML格式来传输太耗流量了,想最好能改成使用JSON格式传输。但是之前的XML格式也要保留,最好可以由客户端指定使用哪种格式。

你有些不开心,心里低估着,为什么一开始不考虑周全呢,现在又要改遗留代码。但对方毕竟是领导,你还是要服从命令的,于是你开始修改Formatter类:

  1. public class Formatter {
  2. public static final int XML = 0;
  3. public static final int JSON = 1;
  4. public String formatBook(Book book, int format) {
  5. System.out.println("format begins");
  6. String result = "";
  7. if (format == XML) {
  8. result += "<book_name>" + book.getBookName() + "</book_name>\n";
  9. result += "<pages>" + book.getPages() + "</pages>\n";
  10. result += "<price>" + book.getPrice() + "</price>\n";
  11. result += "<author>" + book.getAuthor() + "</author>\n";
  12. result += "<isbn>" + book.getIsbn() + "</isbn>\n";
  13. } else if (format == JSON) {
  14. result += "{\n";
  15. result += "\"book_name\" : \"" + book.getBookName() + "\",\n";
  16. result += "\"pages\" : \"" + book.getPages() + "\",\n";
  17. result += "\"price\" : \"" + book.getPrice() + "\",\n";
  18. result += "\"author\" : \"" + book.getAuthor() + "\",\n";
  19. result += "\"isbn\" : \"" + book.getIsbn() + "\",\n";
  20. result += "}";
  21. }
  22. System.out.println("format finished");
  23. return result;
  24. }
  25. }

调用代码如下:

  1. public class Test {
  2. public static void main(String[] args) throws Exception {
  3. Book book = new Book();
  4. book.setBookName("Thinking in Java");
  5. book.setPages(880);
  6. book.setPrice(68);
  7. book.setAuthor("Bruce Eckel");
  8. book.setIsbn("9787111213826");
  9. Formatter formatter = new Formatter();
  10. String result = formatter.formatBook(book, Formatter.XML);
  11. System.out.println(result);
  12. result = formatter.formatBook(book, Formatter.JSON);
  13. System.out.println(result);
  14. }
  15. }

再次运行程序,得到了以下结果。

项目经理看到运行结果后开心地说:“太好了,这正是我想要的!”

可是你这次却没有那么开心,你觉得代码已经有些混乱了,XML格式的逻辑和JSON格式的逻辑混淆在一起,非常不利于阅读,而且如果以后还需要扩展功能也会非常困难。好在传输格式一般也就XML和JSON了,应该不会再有什么扩展了,你这样安慰自己道。

但幻想总会被现实打破,“我最近听说有个YAML格式挺好玩的.......” 项目经理说道。这个时候你已经有想打人的冲动了!!!

很多时候就是这样,在公司里写的代码乱七八糟,质量极差,很大一部分原因就是因为需求变来变去。我们不断在原有代码基础上补充各种后续加入的情况,在一行行新增的if语句下面,我们的代码变得不堪入目。当然,我们作为程序员,对于需求这种东西没有太多的话语权,在这方面我们无能为力。但是我们可以尽量地把程序的架构设计好,让我们写出的代码更具有扩展性,这样就可以应对各种需求变更了。

下面你将要使用23种设计模式中的模板方法来改进以上程序。

首先将Formatter中的代码进行修改,如下所示:

  1. public abstract class Formatter {
  2. public String formatBook(Book book, int format) {
  3. beforeFormat();
  4. String result = formating(book);
  5. afterFormat();
  6. return result;
  7. }
  8. protected void beforeFormat() {
  9. System.out.println("format begins");
  10. }
  11. protected abstract String formating(Book book);
  12. protected void afterFormat() {
  13. System.out.println("format finished");
  14. }
  15. }

你会发现format_book方法只有四步,第一步调用before_format,去打印格式转换前的日志。第二步调用formating,这个方法是个抽象方法,用于处理具体的转换逻辑,因此每一个继承自Formatter的子类都需要重写此方法,来实现各自的转换逻辑。第三步调用after_format,去打印格式转换后的日志。第四步返回result。由于类中存在了抽象方法,我们也就需要把Formatter声明成抽象类。

然后要定义专门的子类来处理每种传输格式的具体逻辑,这样不同传输格式的逻辑可以从一个方法里分离开,明显便于阅读和理解。

定义类XMLFormatter继承自Formatter,里面加入处理XML格式的具体逻辑:

  1. public class XMLFormatter extends Formatter {
  2. @Override
  3. protected String formating(Book book) {
  4. String result = "";
  5. result += "<book_name>" + book.getBookName() + "</book_name>\n";
  6. result += "<pages>" + book.getPages() + "</pages>\n";
  7. result += "<price>" + book.getPrice() + "</price>\n";
  8. result += "<author>" + book.getAuthor() + "</author>\n";
  9. result += "<isbn>" + book.getIsbn() + "</isbn>\n";
  10. return result;
  11. }
  12. }

定义类JSONFormatter继承自Formatter,里面加入处理JSON格式的具体逻辑:

  1. public class JSONFormatter extends Formatter {
  2. @Override
  3. protected String formating(Book book) {
  4. String result = "";
  5. result += "{\n";
  6. result += "\"book_name\" : \"" + book.getBookName() + "\",\n";
  7. result += "\"pages\" : \"" + book.getPages() + "\",\n";
  8. result += "\"price\" : \"" + book.getPrice() + "\",\n";
  9. result += "\"author\" : \"" + book.getAuthor() + "\",\n";
  10. result += "\"isbn\" : \"" + book.getIsbn() + "\",\n";
  11. result += "}";
  12. return result;
  13. }
  14. }

最后调用代码如下:

  1. public class Test {
  2. public static void main(String[] args) throws Exception {
  3. Book book = new Book();
  4. book.setBookName("Thinking in Java");
  5. book.setPages(880);
  6. book.setPrice(68);
  7. book.setAuthor("Bruce Eckel");
  8. book.setIsbn("9787111213826");
  9. XMLFormatter xmlFormatter = new XMLFormatter();
  10. String result = xmlFormatter.formatBook(book);
  11. System.out.println(result);
  12. JSONFormatter jsonFormatter = new JSONFormatter();
  13. result = jsonFormatter.formatBook(book);
  14. System.out.println(result);
  15. }
  16. }

运行之后,你会发现运行结果和修改前代码的运行结果完全相同。但是使用模板方法之后,代码的可读性有了很大的提高,因为处理格式转换的代码都放到了各自的类当中,而不是全部塞进一个方法中。并且在扩展性上也有了很大的提升,比如你开始感兴趣项目经理说的YAML格式了。

定义类YAMLFormatter继承自Formatter,里面加入处理YAML格式的具体逻辑:

  1. public class YAMLFormatter extends Formatter {
  2. @Override
  3. protected String formating(Book book) {
  4. String result = "";
  5. result += "book_name: " + book.getBookName() + "\n";
  6. result += "pages: " + book.getPages() + "\n";
  7. result += "price: " + book.getPrice() + "\n";
  8. result += "author: " + book.getAuthor() + "\n";
  9. result += "isbn: " + book.getIsbn() + "\n";
  10. return result;
  11. }
  12. }

调用代码只需要加入:

  1. YAMLFormatter yamlFormatter = new YAMLFormatter();
  2. String result = yamlFormatter.formatBook(book);
  3. System.out.println(result);

好了,令人头疼的YAML格式就这样被支持了,只需要在调用的时候决定是实例化XMLFormatter,JSONFormatter还是YAMLFormatter,就可以按照相应的规格进行格式转换了。而且整体的代码很有条理,看起来也很舒心。这个时候,你会轻松地向项目经理调侃一句,还有需要支持的格式吗?

模板方法: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

java设计模式之模板方法的更多相关文章

  1. 折腾Java设计模式之模板方法模式

    博客原文地址:折腾Java设计模式之模板方法模式 模板方法模式 Define the skeleton of an algorithm in an operation, deferring some ...

  2. java 设计模式之模板方法

    模板方法的定义 定义了一个算法的骨架,并允许子类为一个或多个步骤提供实现. 模板方法使得子类在不改变算法结构的情况下,重新定义某些算法的步骤. 一次性实现一个算法不变的部分,把可变的行为留给子类实现. ...

  3. Java设计模式应用——模板方法模式

    所谓模板方法模式,就是在一组方法结构一致,只有部分逻辑不一样时,使用抽象类制作一个逻辑模板,具体是实现类仅仅实现特殊逻辑就行了.类似科举制度八股文,文章结构相同,仅仅具体语句有差异,我们只需要按照八股 ...

  4. [译]Java 设计模式 之模板方法

    (文章翻译自Java Design Pattern: Template Method) 模板方法设计模式定义了归档特定操作的工作流.它允许子类去修改特定的步奏而不用改变工作流的结构. 下面的例子表示模 ...

  5. Java设计模式之模板方法设计模式(银行计息案例)

    不知道为什么,这几天对Java中的设计模式非常感兴趣,恰巧呢这几天公司的开发任务还不算太多,趁着有时间昨天又把模板方法模式深入学习了一下,做了一个客户在不同银行计息的小案例,感触颇深,今天给各位分享一 ...

  6. Java设计模式之 — 模板方法(Template Method)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8744002 今天你还是像往常一样来上班,一如既往地开始了你的编程工作. 项目经理告 ...

  7. Java设计模式之模板方法模式(Template)

    前言: 我们在开发中有很多固定的流程,这些流程有很多步凑是固定的,比如JDBC中获取连接,关闭连接这些流程是固定不变的,变动的只有设置参数,解析结果集这些是根据不同的实体对象“来做调整”,针对这种拥有 ...

  8. java设计模式之模板方法模式

    模板方法模式 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中. 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤.通俗的说的就是有很多相同的步骤的,在某一些地方可能有一些差 ...

  9. Java设计模式之模板方法模式(Template Method)

    一.含义 定义一个算法中的操作框架,而将一些步骤延迟到子类中.使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤,不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现. 二 ...

随机推荐

  1. 洛谷P4609 [FJOI2016]建筑师(第一类斯特林数+组合数)

    题面 洛谷 题解 (图片来源于网络,侵删) 以最高的柱子\(n\)为分界线,我们将左边的一个柱子和它右边的省略号看作一个圆排列,右边的一个柱子和它左边的省略号看作一个圆排列,于是,除了中间的最高的柱子 ...

  2. 2017广西邀请赛 Query on A Tree (可持续化字典树)

    Query on A Tree 时间限制: 8 Sec  内存限制: 512 MB提交: 15  解决: 3[提交][状态][讨论版] 题目描述 Monkey A lives on a tree. H ...

  3. Heavy Transportation(POJ - 1797 变形版 dijkstra)

    Background Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand bus ...

  4. 【LA 3641】 Leonardo's Notebook (置换群)

    [题意] 给出26个大写字母组成 字符串B问是否存在一个置换A使得A^2 = B [分析] 置换前面已经说了,做了这题之后有了更深的了解. 再说说置换群.   首先是群. 置换群的元素是置换,运算时是 ...

  5. Activit(活动)实践--知晓当前活动

    实际上,我们可能用的不是自己写的项目,而是从别人那里接手过来的代码,因为你刚进公司就有一个新项目开始的概率十分低.阅读别人代码时会有一个很头疼的问题,就是当你需要在某个界面上修改一些非常简单的东西时, ...

  6. <摘录>perl正则表达式中的元字符、转义字符、量词及匹配方式

    Linux平台上被广泛使用的正则表达式库PCRE - Perl-compatible regular expressions,从其名字即可知道,PCRE提供的是一套与Perl中相兼容的正则表达式. 元 ...

  7. 【mybatis】mybatis中放置IN查询拼接sql过长,IN查询进行分批次查询的处理

    需要使用的切割list集合的工具类,链接:https://www.cnblogs.com/sxdcgaq8080/p/9376947.html 处理逻辑,原本的一个LIst,进行切割,循环进行myba ...

  8. WinCE5.0开发环境的建立

    目前WinCE5.0的开发工具主要有以下几种:Platform Builder5.0.EVC4.0+SP4.Visual Studio2005.其中Platform Builder主要用于定制WinC ...

  9. 手机APP上中下三层

    代码如下: <template> <div class="container" id="app"> <header> < ...

  10. C语言void关键字的深刻含义

    C语言void关键字的深刻含义 .概述 本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧. .void的含义 void的字面意思是“无类型”,void *则为 ...