码迷,mamicode.com
首页 > 其他好文 > 详细

建造者模式

时间:2016-09-17 00:34:11      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:

对于建造者模式,我们首先来说明建造者模式是用来干嘛的。建造模式一般用于创建复杂对象,这些复杂对象的构建过程是稳定的,但是内部的构件通常要面临比较复杂的变化。怎么来解释呢?我们利用《大话设计模式》中的例子来解释,创建一个胖子和一个瘦子,我们需要画出头、手、脚、身体这几个部分,最没水平的写法是写两个类,一个胖子类,一个瘦子类,这不像我们一门面向对象语言所写出来的代码。通常我们可能会抽象出一个创建人的接口,并有画出头、手、脚、身体这几个抽象方法,胖子、瘦子分别来实现这几个方法,但是我们还需要将这几个方法组装起来,建造者模式利用一个指挥者类来控制建造过程,但是集绕我们的建造过程是稳定的,我们是否可以在我们出来的创建人接口修改为抽象类,定义一个建造方法呢?咦,写到这个地方,我发现好像建造者模式是不是把问题复杂化了?我们来通过这两周方法来对比看看。

我们先来看看我们通常所做的方法来实现这个创建胖子、瘦子的需求:


 

第一种方法

创建人的抽象类:

 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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!