论坛首页 Java企业应用论坛

java设计模式全解[3]-建造者模式

浏览 10401 次
精华帖 (1) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-06-11  

建造者模式

这个是zmo_xu的java设计模式系列的第三章.这里需要说明一下 我这里给出的代码并不是标准代码,应该说是我自己的学习笔记,拿出来与大家交流,也希望各位高手多多指教,在这里感谢javastudy给予的帮助!(感谢CCTV ,感谢父母 感谢滚石娱乐的什么就不说了 呵呵  好了 老规矩 言归正传[保存下 哈哈 ])

概述
在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法确相对稳定。如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?这就是要说的建造者模式。
本文通过现实生活中的买KFC的例子,用图解的方式来诠释建造者模式。
意图
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
[注意:所有的设计模式都不是为了使我们的代码更简单,正恰恰相反 是更复杂,设计模式的目的 是提高 代码的重用  降低模块的耦合]{打听下怎么用最快的方法把word 里面的图片发上来 ....相册的方法就不要说了...}

 生活中的例子
生成器模式将复杂对象的构建与对象的表现分离开来,这样使得同样的构建过程可以创建出不同的表现。这种模式用于快餐店制作儿童餐。典型的儿童餐包括一个主食,一个辅食,一杯饮料和一个玩具(例如汉堡、炸鸡、可乐和玩具车)。这些在不同的儿童餐中可以是不同的,但是组合成儿童餐的过程是相同的。无论顾客点的是汉堡,三名治还是鸡肉,过程都是一样的。柜台的员工直接把主食,辅食和玩具放在一起。这些是放在一个袋子中的。饮料被倒入杯中,放在袋子外边。这些过程在相互竞争的餐馆中是同样的。


客户端:顾客。想去买一套套餐(这里面包括汉堡,可乐,薯条),可以有1号和2号两种套餐供顾客选择。
指导者角色:收银员。知道顾客想要买什么样的套餐,并告诉餐馆员工去准备套餐。
建造者角色:餐馆员工。按照收银员的要求去准备具体的套餐,分别放入汉堡,可乐,薯条等。
产品角色:最后的套餐,所有的东西放在同一个盘子里面。
下面开始我们的买套餐过程。
1.客户创建Derector对象,并用它所想要的Builder对象进行配置。顾客进入KFC店要买套餐,先找到一个收银员,相当于创建了一个指导者对象。这位收银员给出两种套餐供顾客选择:1普通套餐,2黄金套餐。完成的工作如时序图中红色部分所示。
[养成保存文件的习惯 web程序也不例外]

  1. package unit3_Buider;   
  2.   
  3. import java.util.ResourceBundle;   
  4.   
  5. public class Client   
  6. {   
  7.   
  8.     public Client()   
  9.     {   
  10.     }   
  11.   
  12.     /**  
  13.      * @param args  
  14.      */  
  15.     public static void main(String[] args)   
  16.     {   
  17.         //设置配置文件 文件名   
  18.         String configFile="food.properties";   
  19.         FoodManager foodmanager = new FoodManager();   
  20.   
  21.         Builder instance;   
  22.   
  23.         System.out.println("Please Enter Food No:");   
  24.   
  25.         String No = 1+"";   
  26.         ResourceBundle bundle = ResourceBundle.getBundle(configFile);   
  27.         //String foodType = ConfigurationSettings.AppSettings["No" + No];   
  28.         String foodType=bundle.getString("No"+No);   
  29.   
  30.         try  
  31.         {   
  32.             instance = (Builder) Class.forName(foodType).newInstance();   
  33.   
  34.             foodmanager.Construct(instance);   
  35.         }   
  36.         catch (InstantiationException e)   
  37.         {   
  38.             e.printStackTrace();   
  39.         }   
  40.         catch (IllegalAccessException e)   
  41.         {   
  42.             e.printStackTrace();   
  43.         }   
  44.         catch (ClassNotFoundException e)   
  45.         {   
  46.             e.printStackTrace();   
  47.         }   
  48.   
  49.     }   
  50.   
  51. }   

唉又一次华丽的提交失败了

产品(套餐)类:<o:p></o:p>

java 代码

  1. package unit3_Buider;   
  2.   
  3. import java.util.Enumeration;   
  4. import java.util.Hashtable;   
  5.   
  6. public class Food   
  7. {   
  8.     Hashtable food = new Hashtable();   
  9.   
  10.     public void Add(String strName, String Price)   
  11.     {   
  12.         food.put(strName, Price);   
  13.     }   
  14.     public void Show()   
  15.     {   
  16.         System.out.println("Food List:");   
  17.         System.out.println("------------------------------");   
  18.          for (Enumeration e = food.elements(); e.hasMoreElements() ;) {   
  19.              System.out.println(e.nextElement());   
  20.          }   
  21.          System.out.println("\n------------------------------");   
  22.     }   
  23.   
  24. }   

保存点

 2.指导者通知建造器。收银员(指导者)告知餐馆员工准备套餐。这里我们准备套餐的顺序是:放入汉堡,可乐倒入杯中,薯条放入盒中,并把这些东西都放在盘子上。这个过程对于普通套餐和黄金套餐来说都是一样的,不同的是它们的汉堡,可乐,薯条价格不同而已。如时序图红色部分所示:

java 代码

  1. package unit3_Buider;   
  2.   
  3. public class FoodManager   
  4. {   
  5.   
  6.     public FoodManager()   
  7.     {   
  8.     }   
  9.   
  10.     public void Construct(Builder builder)   
  11.     {   
  12.         builder.BuildHamb();   
  13.   
  14.         builder.BuildCoke();   
  15.   
  16.         builder.BuildChip();   
  17.     }   
  18.   
  19. }   

 3.建造者处理指导者的要求,并将部件添加到产品中。餐馆员工(建造者)按照收银员要求的把对应的汉堡,可乐,薯条放入盘子中。这部分是建造者模式里面富于变化的部分,因为顾客选择的套餐不同,套餐的组装过程也不同,这步完成产品对象的创建工作。
程序实现:

java 代码

  1. package unit3_Buider;   
  2.   
  3. public abstract class Builder   
  4. {   
  5.   
  6.     public Builder()   
  7.     {   
  8.     }   
  9.   
  10.     public abstract void BuildHamb();   
  11.   
  12.     /*  
  13.      *  添加可乐  
  14.      */  
  15.     public abstract void BuildCoke();   
  16.   
  17.     /**  
  18.      * 添加薯条  
  19.      */  
  20.     public abstract void BuildChip();   
  21.   
  22.     /**  
  23.      * 返回结果  
  24.      * @return 食品对象  
  25.      */  
  26.     public abstract Food GetFood();   
  27.   
  28. }   

今天就写到这里晚了  这样写好累的说  郁闷都没人顶下 动力啊  ....55555

具体的建造者

java 代码
  1. package zmo;   
  2.   
  3. public class GoldBuilder extends Builder   
  4. {   
  5.   
  6.     //黄金套餐的配餐员   
  7.     private Food goldFood=null;   
  8.     public GoldBuilder()   
  9.     {   
  10.         this.goldFood=new Food();   
  11.     }   
  12.   
  13.     @Override  
  14.     public void BuildChip()   
  15.     {   
  16.         goldFood.Add("GoldChip""5.00");   
  17.     }   
  18.   
  19.     @Override  
  20.     public void BuildCoke()   
  21.     {   
  22.         goldFood.Add("CokeCole""5.00");   
  23.     }   
  24.   
  25.     @Override  
  26.     public void BuildHamb()   
  27.     {   
  28.         goldFood.Add("GoldHamb""13.50");   
  29.     }   
  30.   
  31.     @Override  
  32.     public Food GetFood()   
  33.     {   
  34.         return goldFood;   
  35.     }   
  36.   
  37. }   
java 代码
  1. package zmo;   
  2.   
  3. public class NormalBuilder extends Builder   
  4. {   
  5.   
  6.     //普通套餐的配餐员   
  7.     private Food normalFood=null;   
  8.     public NormalBuilder()   
  9.     {   
  10.         normalFood=new Food();   
  11.     }   
  12.   
  13.     @Override  
  14.     public void BuildChip()   
  15.     {   
  16.         //添加薯条   
  17.         normalFood.Add("FireChips""2.00");   
  18.     }   
  19.   
  20.     @Override  
  21.     public void BuildCoke()   
  22.     {   
  23.         //添加可乐   
  24.         normalFood.Add("cokecole""5.00");   
  25.     }   
  26.   
  27.     @Override  
  28.     public void BuildHamb()   
  29.     {   
  30.         //添加汉堡   
  31.         normalFood.Add("NormalHamb""1.00");   
  32.     }   
  33.   
  34.     @Override  
  35.     public Food GetFood()   
  36.     {   
  37.         return normalFood;   
  38.     }   
  39.   
  40. }   
java 代码
  1. package zmo;   
  2.   
  3. import java.io.BufferedReader;   
  4. import java.io.IOException;   
  5. import java.io.InputStreamReader;   
  6. import java.util.ResourceBundle;   
  7.   
  8.   
  9. public class Client   
  10. {   
  11. //模拟顾客点菜   
  12.   
  13.     /**  
  14.      * @param args  
  15.      */  
  16.     public static void main(String[] args)   
  17.     {   
  18.         FoodManager foodmanager = new FoodManager();   
  19.         Builder instance;   
  20.         //设置配置文件 文件名   
  21.         String configFile="food";   
  22.         ResourceBundle bundle = ResourceBundle.getBundle(configFile);   
  23.         String No="";   
  24.         do  
  25.         {   
  26.             System.out.println(bundle.getString("List"));   
  27.             No =inputString();   
  28.         }while(No.equals("")||No==null);   
  29.         String foodType = bundle.getString("No"+No);   
  30.         //String foodType="zmo.NormalBuilder";   
  31.   
  32.         try  
  33.         {   
  34.             instance = (Builder) Class.forName(foodType).newInstance();   
  35.             foodmanager.Construct(instance);   
  36.             Food food=instance.GetFood();   
  37.             food.Show();   
  38.         }   
  39.         catch (InstantiationException e)   
  40.         {   
  41.             e.printStackTrace();   
  42.         }   
  43.         catch (IllegalAccessException e)   
  44.         {   
  45.             e.printStackTrace();   
  46.         }   
  47.         catch (ClassNotFoundException e)   
  48.         {   
  49.             e.printStackTrace();   
  50.         }   
  51.   
  52.     }   
  53.     /**  
  54.      * 用于从控制台获取输入  
  55.      * @return  
  56.      */  
  57.     private static String inputString()   
  58.     {   
  59.         BufferedReader bufferedreader = new BufferedReader(   
  60.         new InputStreamReader(System.in));   
  61.         String s = null;   
  62.         try  
  63.         {   
  64.   
  65.             s = bufferedreader.readLine();   
  66.   
  67.         } catch (IOException ioexception)   
  68.         {   
  69.             ioexception.printStackTrace();   
  70.         }   
  71.         return s;   
  72.     }   
  73. }   

food.properties文件放在src下其内容
List=1.Normal  \n2.Gold  \nPlease input the noumber
No1=zmo.NormalBuilder
No2=zmo.GoldBuilder

javastudy 你要的uml在附件的项目里面 我已经生成了uml  欢迎大家讨论 最后附上源代码


追加说明:
实现要点
1、建造者模式主要用于“分步骤构建一个复杂的对象”,在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。
2、产品不需要抽象类,特别是由于创建对象的算法复杂而导致使用此模式的情况下或者此模式应用于产品的生成过程,其最终结果可能差异很大,不大可能提炼出一个抽象产品类。
3、创建者中的创建子部件的接口方法不是抽象方法而是空方法,不进行任何操作,具体的创建者只需要覆盖需要的方法就可以,但是这也不是绝对的,特别是类似文本转换这种情况下,缺省的方法将输入原封不动的输出是合理的缺省操作。
4、前面我们说过的抽象工厂模式(Abtract Factory)解决“系列对象”的需求变化,Builder模式解决“对象部分”的需求变化,建造者模式常和组合模式(Composite Pattern)结合使用。
效果
1、建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。
2、每一个Builder都相对独立,而与其它的Builder无关。
3、可使对构造过程更加精细控制。
4、将构建代码和表示代码分开。
5、建造者模式的缺点在于难于应付“分步骤构建算法”的需求变动。
适用性
以下情况应当使用建造者模式:
1、需要生成的产品对象有复杂的内部结构。
2、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
应用场景
1、   根据properties文件或者class文件来知道builder
2、   .......
总结
建造者模式的实质是解耦组装过程和创建具体部件,使得我们不用去关心每个部件是如何组装的。

  • Builder.rar (19.3 KB)
  • 描述: 用kfc模拟了一个建造者模式
  • 下载次数: 263
   发表时间:2007-06-12  
uml图片..我已经把uml生成在项目里面 了 发图片不知道能不能直接粘贴 我就放在项目文件里面了
0 请登录后投票
   发表时间:2007-07-24  
好像不是原创的吧,是不是把别人的文章稍微改了改
http://www.njpro.cn/Forums/thread/28909.aspx
http://tech.it168.com/n/2007-05-08/200705081703234_1.shtml

尤其是这一段和别人的一摸一样的,楼主可能要看看版规了
实现要点

1、建造者模式主要用于“分步骤构建一个复杂的对象”,在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。

2、产品不需要抽象类,特别是由于创建对象的算法复杂而导致使用此模式的情况下或者此模式应用于产品的生成过程,其最终结果可能差异很大,不大可能提炼出一个抽象产品类。
3、创建者中的创建子部件的接口方法不是抽象方法而是空方法,不进行任何操作,具体的创建者只需要覆盖需要的方法就可以,但是这也不是绝对的,特别是类似文本转换这种情况下,缺省的方法将输入原封不动的输出是合理的缺省操作。

4、前面我们说过的抽象工厂模式(Abtract Factory)解决“系列对象”的需求变化,Builder模式解决“对象部分”的需求变化,建造者模式常和组合模式(Composite Pattern)结合使用。

效果

1、建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。
2、每一个Builder都相对独立,而与其它的Builder无关。
3、可使对构造过程更加精细控制。

4、将构建代码和表示代码分开。

5、建造者模式的缺点在于难于应付“分步骤构建算法”的需求变动。

适用性

以下情况应当使用建造者模式:

1、需要生成的产品对象有复杂的内部结构。
2、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。

应用场景

0 请登录后投票
   发表时间:2007-08-15  
我的文章是参考某.net大老的设计模式写的 .我在系列文章的第一章里面就说明了 这一点 我并没有说 所有的都是原创的啊
0 请登录后投票
   发表时间:2007-09-04  
不知道楼主可不可以写一个关于PROTOTYPE模式的文章,我对这个不是很了解,谢谢。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics