转载请注明出处: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. webpack HMR原理

    在启动 devServer 的时候,sockjs 在服务端和浏览器端建立了一个 webSocket 长连接,以便将 webpack 编译和打包的各个阶段状态告知浏览器,最关键的步骤还是 webpack ...

  2. matlab学习之绘制参数曲线,添加辅助线以及颜色设置

    粘贴代码 % 插入参数曲线h % 插入辅助线h1 % 并设置颜色,包括画布颜色和曲线颜色 t=-pi:0.1:pi; x=cos(t)-sin(3*t); y=sin(t).*cos(t)-cos(3 ...

  3. 北大青鸟代码---asp.net初学者宝典

    一.上传图片:使用控件:file,button,image; 上传按钮的代码: string fullfilename=this.File1 .PostedFile .FileName ;取得本地文件 ...

  4. 【带权并查集】【离散化】vijos P1112 小胖的奇偶

    每个区间拆成r和l-1两个端点,若之内有偶数个1,则这两个端点对应的前缀的奇偶性必须相同,否则必须相反. 于是可以用带权并查集维护,每个结点储存其与其父节点的奇偶性是否相同,并且在路径压缩以及Unio ...

  5. [转]SpringMVC拦截器详解[附带源码分析]

      目录 前言 重要接口及类介绍 源码分析 拦截器的配置 编写自定义的拦截器 总结 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:ht ...

  6. 每天一个linux命令21之ln: linux 下的软链和硬链

    首先理解一下一下inode:Unix/Linux系统内部不使用文件名,而使用inode号码来识别文件. 表面上,用户通过文件名,打开文件.实际上,系统内部这个过程分成三步:首先,系统找到这个文件名对应 ...

  7. quartz做集群配置较短的时间间隔会重复执行任务的问题

    quartz.properties org.quartz.jobStore.misfireThreshold = 60000 这个参数(单位为毫秒)设置了以后就是超时1min的就不执行,小于1min会 ...

  8. Oracle 11gR2 RAC连接时ORA-12545错误

    刚装成的Oracle 11gR2的RAC集群 三个节点 创建好数据库,一切都在正常的进行中 然后去安装了一个oracle client,进行链接时出现了ORA-12545 然后简单的baidu了一下, ...

  9. 8.8.8.8和8.8.4.4 DNS域名解析服务器

    而Google表示推出免费DNS服务的主要目的就是为了改进网络浏览速度.改善网络用户的浏览体验,为此Google自行开发的软件对DNS服务器技术进行了改进,通过采用预获取技术提升性能,同时保证了DNS ...

  10. 二十四种设计模式:代理模式(Proxy Pattern)

    代理模式(Proxy Pattern) 介绍为其他对象提供一个代理以控制对这个对象的访问. 示例有一个Message实体类,某对象对它的操作有Insert()和Get()方法,用一个代理来控制对这个对 ...