转载请申明出处:http://blog.csdn.net/qq_24692041/article/details/79277901
开篇引言
在开发中尤其注重代码的可迭代性,这就侧重了功能解耦和类之间的解耦。因为在一个功能更改或者新功能加入的时候,我们尽量
不修改之前的类,而是增加新类中实现新的功能,或者只需要更改指定的类来实现新功能。所以在功能更改的时候,代码的可替换
性就显得十分重要,在旧的逻辑代码中,将旧的功能类替换为新的功能类即可。
具体案例分析
的文档书写,如果都放到同一个类中书写,当我们更改其中一种书写方式的时候,可能不小心就破坏了其他类型文档的实现。这就是单一功能原则存在的原因。虽然各类型的书写格式不相同,但是最终实现的功能却是一致的,都是写文档,所以我们可以有一个父类具体约束好一个结构,但是不具体的实现,让每一种类型的文档具体去实现自己的书写格式。
案例架构分析
现在需求是编写一个书写文档的程序,写出的文档具体内容结构如下:
- 有标题
- 有内容
- 内容分为几个条目
现在我们书写一个抽象类Builder,用于定义文档结构。然后书写Director类用于调用builder类的方法实现编写文档功能。另外需要两个Builder的子类执行不同文档类型的书写任务。
TextBuilder类执行text文档书写任务。HtmlBuilder类执行HTML文档书写任务
具体实现代码
/** * <p> * Builder类,定义了整个功能的结构,具体的功能由子类执行 * <p> * Created by PICO-USER Dragon on 2018/2/7. */ public abstract class Builder { public abstract void makeTitle(String _title); public abstract void makeString(String _str); public abstract void makeItems(String[] _items); public abstract void close(); public abstract String getResultStr(); }
/** * Director类 用于功能的完成,但是不会指定具体的功能是什么 * <p> * Created by PICO-USER Dragon on 2018/2/7. */ public class Director { private Builder mBuilder; public Director(Builder _builder) { this.mBuilder = _builder; } public void createTitle(String _title) { mBuilder.makeTitle(_title); } public void createContent(String _str, String[] _items) { mBuilder.makeString(_str); mBuilder.makeItems(_items); } public void complete() { mBuilder.close(); String resultStr = mBuilder.getResultStr(); System.out.print(resultStr); } }
/** * TextBuilder类 用于实现具体的功能(编写文本文档) * <p> * Created by PICO-USER on 2018/2/7. */ public class TextBuilder extends Builder { private StringBuffer buffer = new StringBuffer(); @Override public void makeTitle(String _title) { buffer.append("===================================\n"); buffer.append("[ " + _title + " ]\n"); buffer.append("\n"); } @Override public void makeString(String _str) { buffer.append("@" + _str + "\n"); buffer.append("\n"); } @Override public void makeItems(String[] _items) { for (int i = 0; i < _items.length; i++) { buffer.append(" . " + _items[i] + "\n"); } buffer.append("\n"); } @Override public void close() { buffer.append("===================================\n"); buffer.append("complete\n"); } @Override public String getResultStr() { return buffer.toString(); } }
/** * HtmlBuilder类 用于具体的功能实现(编写HTML文档) * Created by PICO-USER Dragon on 2018/2/7. */ public class HtmlBuilder extends Builder { private String fileName; private PrintWriter writer; @Override public void makeTitle(String _title) { fileName = _title + ".html"; try { writer = new PrintWriter(new FileWriter(fileName)); } catch (IOException e) { e.printStackTrace(); } writer.println("<html><head><title>" + _title + "</title></head><body>"); writer.println("<h1>" + _title + "</h1>"); } @Override public void makeString(String _str) { writer.println("<p>" + _str + "</p>"); } @Override public void makeItems(String[] _items) { writer.println("<ul>"); for (int i = 0; i < _items.length; i++) { writer.println("<li>" + _items[i] + "</li>"); } writer.println("</ul>"); } @Override public void close() { writer.println("</body></html>"); writer.close(); } @Override public String getResultStr() { return fileName; } }
/** * 程序入口,调用Director类实现具体的功能,并且决定每一个功能的实现逻辑 */ public class Main { public static void main(String[] args) { TextBuilder textBuilder = new TextBuilder(); Director director = new Director(textBuilder); director.createTitle("Greeting"); director.createContent("Morning", new String[]{"good morning", "good afternoon"}); director.createContent("Night", new String[]{"good evening", "good night"}); director.complete(); HtmlBuilder htmlBuilder = new HtmlBuilder(); Director director1 = new Director(htmlBuilder); director1.createTitle("Greeting"); director1.createContent("Morning", new String[]{"good morning", "good afternoon"}); director1.createContent("Night", new String[]{"good evening", "good night"}); director1.complete(); } }
代码分析
在上面的功能实现种,有一个尤其重要的概念,也就是“知道谁”的概念。也就是说在写代码的时候,我们要注意几个问题:那个
类需要调用那个类的方法,不能调用那个类的方法,调用这个类的方法好不好。 我们回头看看实例代码:Main类只是调用了
Director类的方法就实现了不同类型文档的编写,Main并不知道最终完成每一种文档类型是谁完成的,具体是通过什么方式去完
成的。Main也没必要知道,因为Main只需要知道Director能完成就行,只需要跟Director进行交互,这样就避免了更多的类之间
的耦合,也更满足职责单一原则。 而Director也只是调用了Builder类的方法实现了不同类型的文档书写,它并不知道具体“是谁”
完成了它所指派的任务,并且它也没必要知道,因为它的任务只是指派文档的书写,而接受这个任务的人应该是Builder,跟别人
没关系,这同样是避免了更多类的耦合,同样满足职责单一原则。也正是因为这种代码风格才有了Director不知道子类,才能进行
子类替换的这么一个功能,不论将Builder的哪一个子类传给Director都能实现文档的书写,也就是说对于Director来说Builder的
子类具体是谁来完成任务,他根本不care,谁来完成都行,这样代码也就更灵活,需要不同功能的时候,只需要替换传给Director的
Builder子类即可。
总结
因为不知道是谁,才能替换,组件才具有高效性。作为开发人员,必须时刻注意代码的质量,注意“可替换性”。