建造者模式(Builder)
### Builder ?
在建造大楼时,需要先打牢地基,搭建框架,然后自下而上地一层一层盖起来。通常,在建造这种具有复杂结构的物体时,很难一气呵成。我们需要首先建造组成这个物体的各个部分,然后分阶段将它们组装起来。(可以理解为按照模块组装)
### 具体职责
– Builder 为你实现主逻辑要实现的抽象方法
– Director 为你具体使用builder完成具体的逻辑使用代码 就是调用Builder的函数实现实际功能
– Director类不知道自己使用的究竟是Builder类的哪个子类也好。这是因为“只有不知道子类才能替换”。不论是将TextBuilder的实例传递给Director,还是将HTMLBuilder类的实例传递给Director,它都可以正常工作,原因正是Director类不知道Builder类的具体的子类。
– xxxx 任何多个具体的实现类
扩展: 这里可以联想到Template Method 设计模式中 由父类控制 子类的使用过程,但是这里换了对象
|Builder 定义了决定文档结构的方法的抽象类
|Director 编写1个文档的类
|TextMovieBuilder| 使用纯文本(普通字符串)编写电影文档的类
|HTMLMovieBuilder| 使用HTML编写电影文档的类
|Main| 测试程序行为的类
### UML
时序图:
例子实现code:
Builder:
’Builder角色负责定义用于生成实例的接口(API)。Builder角色中准备了用于生成实例的方法。
在示例程序中,由Builder类扮演此角色。
1 public abstract class Builder { 2 3 4 5 abstract void makeMovieTitile(String title); 6 7 8 9 abstract void makeMovieBody(String body); 10 11 12 13 abstract void makeMovieItem(String [] items); 14 15 16 17 abstract void close(); 18 19 20 21 }
Director:
Director角色负责使用Builder角色的接口(API)来生成实例。它并不依赖于ConcreteBuilder角色。为了确保不论ConcreteBuilder角色是如何被定义的,Director角色都能正常工作,它只调用在相关实现类的方法
1 public class Director { 2 3 4 5 private Builder builder; 6 7 8 9 public Director(Builder builder) { 10 11 this.builder = builder; 12 13 } 14 15 16 17 /** 18 19 * 具体要建立的实例 20 21 */ 22 23 public void construct(){ 24 25 builder.makeMovieTitile("一步电影的标题"); 26 27 builder.makeMovieBody("引入"); 28 29 builder.makeMovieItem(new String[]{ 30 31 "细节1", 32 33 "细节2", 34 35 36 37 }); 38 39 40 41 builder.makeMovieBody("剧情重点部分"); 42 43 builder.makeMovieItem(new String[]{ 44 45 "细节3", 46 47 "细节4", 48 49 }); 50 51 builder.close(); 52 53 } 54 55 } 56 57 58 59
ConcreteBuilder:
角色是负责实现Builder角色的接口的类(API)。这里定义了在生成实例时实际被调用的方法。此外,在ConcreteBuilder角色中还定义了获取最终生成结果的方法。在示例程序中,由TextMovieBuilder 类和HtmlMovieBuilder 类扮演此角色。
1 public class HtmlMovieBuilder extends Builder { 2 3 4 5 /** 6 7 * 基本html document 8 9 */ 10 11 12 13 private PrintWriter printWriter; 14 15 16 17 @Override 18 19 void makeMovieTitile(String title) { 20 21 String filename="z://"+title+".html"; 22 23 24 25 try { 26 27 printWriter=new PrintWriter(new FileWriter(filename)); 28 29 30 31 printWriter.write("<html><head><title>"+title+"</title></head>"); 32 33 printWriter.write("<h1>"+title+"</h1>"); 34 35 36 37 } catch (IOException e) { 38 39 e.printStackTrace(); 40 41 } 42 43 } 44 45 46 47 @Override 48 49 void makeMovieBody(String body) { 50 51 printWriter.write("<body> <p>"+body+"</p>"); 52 53 } 54 55 56 57 @Override 58 59 void makeMovieItem(String[] items) { 60 61 printWriter.write("<ul>"); 62 63 for (int i = 0; i < items.length ; i++) { 64 65 printWriter.write("<li>"+items[i]+"</li>"); 66 67 } 68 69 printWriter.write("</ul>"); 70 71 } 72 73 74 75 @Override 76 77 void close() { 78 79 printWriter.write("</body></html>"); 80 81 printWriter.close(); 82 83 } 84 85 86 87 public final String getResults(){ 88 89 return printWriter.toString(); 90 91 } 92 93 } 94 95 96 97 98 99 public class TextMovieBuilder extends Builder{ 100 101 private StringBuilder sb=new StringBuilder(); 102 103 104 105 @Override 106 107 void makeMovieTitile(String title) { 108 109 sb.append("=====================\n"); 110 111 sb.append("["+title+"]\n"); 112 113 sb.append("\n"); 114 115 } 116 117 118 119 @Override 120 121 void makeMovieBody(String body) { 122 123 sb.append(body+"\n"); 124 125 sb.append("\n"); 126 127 } 128 129 130 131 @Override 132 133 void makeMovieItem(String[] items) { 134 135 for (int i = 0; i < items.length; i++) { 136 137 sb.append(items[i]+"\n"); 138 139 } 140 141 sb.append("\n"); 142 143 } 144 145 146 147 @Override 148 149 void close() { 150 151 sb.append("====================="); 152 153 } 154 155 156 157 public final String getResults(){ 158 159 return sb.toString(); 160 161 } 162 163 } 164 165
测试:
1 public class MainTest { 2 3 4 5 public static final String HTML = "html"; 6 7 public static final String TEXT = "text"; 8 9 10 11 public static void main(String[] args) { 12 13 14 15 args=new String[]{"html"}; 16 17 18 19 if(args.length!=1||args==null){ 20 21 use(); 22 23 System.exit(0); 24 25 } 26 27 if(HTML.equals(args[0])){ 28 29 30 31 HtmlMovieBuilder movieBuilder = new HtmlMovieBuilder(); 32 33 34 35 Director director = new Director(movieBuilder); 36 37 // 进行构建 38 39 director.construct(); 40 41 42 43 System.out.println(movieBuilder.getResults()); 44 45 46 47 }else if(TEXT.equals(args[0])){ 48 49 50 51 TextMovieBuilder movieBuilder = new TextMovieBuilder(); 52 53 54 55 Director director = new Director(movieBuilder); 56 57 // 进行构建 58 59 director.construct(); 60 61 62 63 // 测试是够构建好了 64 65 System.out.println(movieBuilder.getResults()); 66 67 68 69 }else{ 70 71 use(); 72 73 System.exit(0); 74 75 } 76 77 } 78 79 80 81 private static void use() { 82 83 System.out.println("java xxx html"); 84 85 System.out.println("java xxx text"); 86 87 } 88 89 }