标签:
对于建造者模式,我们首先来说明建造者模式是用来干嘛的。建造模式一般用于创建复杂对象,这些复杂对象的构建过程是稳定的,但是内部的构件通常要面临比较复杂的变化。怎么来解释呢?我们利用《大话设计模式》中的例子来解释,创建一个胖子和一个瘦子,我们需要画出头、手、脚、身体这几个部分,最没水平的写法是写两个类,一个胖子类,一个瘦子类,这不像我们一门面向对象语言所写出来的代码。通常我们可能会抽象出一个创建人的接口,并有画出头、手、脚、身体这几个抽象方法,胖子、瘦子分别来实现这几个方法,但是我们还需要将这几个方法组装起来,建造者模式利用一个指挥者类来控制建造过程,但是集绕我们的建造过程是稳定的,我们是否可以在我们出来的创建人接口修改为抽象类,定义一个建造方法呢?咦,写到这个地方,我发现好像建造者模式是不是把问题复杂化了?我们来通过这两周方法来对比看看。
我们先来看看我们通常所做的方法来实现这个创建胖子、瘦子的需求:
第一种方法
创建人的抽象类:
1 package day_11_createPerson; 2 3 /** 4 * 创建人的抽象类 5 * @author turbo 6 * 7 * 2016年9月16日 8 */ 9 public abstract class Person { 10 public abstract void head(); 11 public abstract void arm(); 12 public abstract void leg(); 13 public abstract void body(); 14 15 public void createPerson(){ 16 head(); 17 arm(); 18 leg(); 19 body(); 20 } 21 }
胖子、瘦子对于头等的建造细节由它们自己去实现,因为小人的建造过程是问题的,所以这里提供一个createPerson具体方法。
下面是胖子、瘦子的实现:
1 package day_11_createPerson; 2 3 /** 4 * 建造胖子 5 * @author turbo 6 * 7 * 2016年9月16日 8 */ 9 public class Fat extends Person { 10 11 /* (non-Javadoc) 12 * @see day_11_createPerson.Person#head() 13 */ 14 @Override 15 public void head() { 16 System.out.println("创建胖子的头"); 17 } 18 19 /* (non-Javadoc) 20 * @see day_11_createPerson.Person#arm() 21 */ 22 @Override 23 public void arm() { 24 System.out.println("创建胖子的手"); 25 } 26 27 /* (non-Javadoc) 28 * @see day_11_createPerson.Person#leg() 29 */ 30 @Override 31 public void leg() { 32 System.out.println("创建胖子的脚"); 33 } 34 35 /* (non-Javadoc) 36 * @see day_11_createPerson.Person#body() 37 */ 38 @Override 39 public void body() { 40 System.out.println("创建胖子的身体"); 41 } 42 43 }
1 package day_11_createPerson; 2 3 /** 4 * 建造瘦子 5 * @author turbo 6 * 7 * 2016年9月16日 8 */ 9 public class Thin extends Person { 10 11 /* (non-Javadoc) 12 * @see day_11_createPerson.Person#head() 13 */ 14 @Override 15 public void head() { 16 System.out.println("创建瘦子的头"); 17 } 18 19 /* (non-Javadoc) 20 * @see day_11_createPerson.Person#arm() 21 */ 22 @Override 23 public void arm() { 24 System.out.println("创建瘦子的手"); 25 } 26 27 /* (non-Javadoc) 28 * @see day_11_createPerson.Person#leg() 29 */ 30 @Override 31 public void leg() { 32 System.out.println("创建瘦子的脚"); 33 } 34 35 /* (non-Javadoc) 36 * @see day_11_createPerson.Person#body() 37 */ 38 @Override 39 public void body() { 40 System.out.println("创建瘦子的身体"); 41 } 42 43 }
客户端测试代码:
1 package day_11_createPerson; 2 3 /** 4 * @author turbo 5 * 6 * 2016年9月16日 7 */ 8 public class Main { 9 10 /** 11 * @param args 12 */ 13 public static void main(String[] args) { 14 Fat fat = new Fat(); 15 fat.createPerson(); 16 17 Thin thin = new Thin(); 18 thin.createPerson(); 19 } 20 21 }
第一种方法简单易懂,并且满足了我们了需求,那第二种利用建造者模式呢?
第二种方法
这里我们要实现一个Product类,这个额外的Product类是用来干嘛的呢?在这里我们的Product代表的就是创建出来的具体的胖子、瘦子“产品”。它由多个部件构成,也就是头、手、腿、身体。
1 package day_11_builder; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * 产品类——由多个部件组成 8 * @author turbo 9 * 10 * 2016年9月16日 11 */ 12 public class Product { 13 private List<String> parts = new ArrayList<String>(); 14 15 public void add(String part){ 16 parts.add(part); 17 } 18 19 public void show(){ 20 for (String part : parts){ 21 System.out.println(part); 22 } 23 } 24 }
接着我们同样有一个建造者,这里是接口,只负责提供创建人的头等的方法,建造过程不由建造者实现,而是由另一个类指挥者(Director)来实现。
1 package day_11_builder; 2 3 /** 4 * 建造者接口 5 * @author turbo 6 * 7 * 2016年9月16日 8 */ 9 public interface Builder { 10 void head(); 11 void arm(); 12 void leg(); 13 void body(); 14 Product getResult(); 15 }
我们来实现这个建造者接口:
1 package day_11_builder; 2 3 /** 4 * @author turbo 5 * 6 * 2016年9月16日 7 */ 8 public class FatBuilder implements Builder { 9 private Product product = new Product(); 10 11 /* (non-Javadoc) 12 * @see day_11_builder.Builder#head() 13 */ 14 @Override 15 public void head() { 16 product.add("创建胖子的头"); 17 } 18 19 /* (non-Javadoc) 20 * @see day_11_builder.Builder#arm() 21 */ 22 @Override 23 public void arm() { 24 product.add("创建胖子的手"); 25 } 26 27 /* (non-Javadoc) 28 * @see day_11_builder.Builder#leg() 29 */ 30 @Override 31 public void leg() { 32 product.add("创建胖子的腿"); 33 } 34 35 /* (non-Javadoc) 36 * @see day_11_builder.Builder#body() 37 */ 38 @Override 39 public void body() { 40 product.add("创建胖子的身体"); 41 } 42 43 /* (non-Javadoc) 44 * @see day_11_builder.Builder#getResult() 45 */ 46 @Override 47 public Product getResult() { 48 return product; 49 } 50 51 }
1 package day_11_builder; 2 3 /** 4 * 具体建造者2 5 * @author turbo 6 * 7 * 2016年9月16日 8 */ 9 public class ThinBuilder implements Builder { 10 private Product product = new Product(); 11 12 /* (non-Javadoc) 13 * @see day_11_builder.Builder#head() 14 */ 15 @Override 16 public void head() { 17 product.add("创建瘦子的头"); 18 } 19 20 /* (non-Javadoc) 21 * @see day_11_builder.Builder#arm() 22 */ 23 @Override 24 public void arm() { 25 product.add("创建瘦子的手"); 26 } 27 28 /* (non-Javadoc) 29 * @see day_11_builder.Builder#leg() 30 */ 31 @Override 32 public void leg() { 33 product.add("创建瘦子的腿"); 34 } 35 36 /* (non-Javadoc) 37 * @see day_11_builder.Builder#body() 38 */ 39 @Override 40 public void body() { 41 product.add("创建瘦子的身体"); 42 } 43 44 /* (non-Javadoc) 45 * @see day_11_builder.Builder#getResult() 46 */ 47 @Override 48 public Product getResult() { 49 return product; 50 } 51 52 }
建造者方法中有一个getResult方法,返回一个Product类型,也就是返回一个具体的产品,具体的胖子还是瘦子。那么我们的建造过程去哪儿了呢?上面提到了由一个指挥者来指挥建造过程。
1 package day_11_builder; 2 3 /** 4 * 指挥者——指挥具体的建造过程 5 * @author turbo 6 * 7 * 2016年9月16日 8 */ 9 public class Director { 10 public void construct(Builder builder){ 11 builder.head(); 12 builder.arm(); 13 builder.leg(); 14 builder.body(); 15 } 16 }
建造者模式将建造过程和实现组件的具体细节相分离。客户端测试代码:
1 package day_11_builder; 2 3 /** 4 * 客户端测试 5 * @author turbo 6 * 7 * 2016年9月16日 8 */ 9 public class Main { 10 public static void main(String[] args){ 11 Director director = new Director(); 12 Builder b1 = new FatBuilder(); 13 Builder b2 = new ThinBuilder(); 14 15 director.construct(b1); 16 Product product1 = b1.getResult(); 17 product1.show(); 18 19 director.construct(b2); 20 Product product2 = b2.getResult(); 21 product2.show(); 22 } 23 }
这样我们就用建造者模式实现了上面创建一个胖子和瘦子的需求。
但是这两种方法到底有什么不同呢?第一种方法确实简单易懂。第二种方法将建造小人各个部分即Builder、具体小人Product、构建过程Director相互分离。到底是第一种方法简单易读好?还是第二种利用建造者模式好呢?(未完,待仔细分析)
标签:
原文地址:http://www.cnblogs.com/yulinfeng/p/5877606.html