原文链接 http://www.cnblogs.com/tjcjxy/archive/2010/11/26/1888660.html
模式名称:生成器模式
1.问题描述
生活场景:你玩过种地、种花等类似的游戏吗?这是最近很流行的游戏哟!下面就是从种花游戏中剪切的四个花盆(盆景),很漂亮吧!你将不同的种子放入花盆,一段时间后你就可以看到各种美丽的鲜花了,不同种子所生产出来的鲜花有不同的花朵、叶子和枝茎。编码该如何实现呢?
设计目标:将种子放入花盆,一段时间后就可以收获美丽的鲜花!
2.不假思索的思路:将盆景看做一个类,有几个盆景我new几个对象,直接完成这一奇妙过程。
设计类图:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
/** * 荷花盆景 */ public class WaterlilyFlowerpot { public String name; // 茎 public String stem; // 叶 public String leaf; // 花 public String flower; public void grow(){ // 说明种类 name = " 荷花 " ; // 生产茎 stem = " 40厘米 " ; // 生产叶子 leaf = " 圆形 " ; // 生产花 flower = " 白里透红 " ; } public void create(){ System.out.println(name + " : 茎 " + " - " + stem + " , 叶 " + " - " + leaf + " , 花 " + " - " + flower); } } /** * 玫瑰盆景 */ public class RoseFlowerpot { public String name; // 茎 public String stem; // 叶 public String leaf; // 花 public String flower; public void grow(){ // 说明种类 name = " 玫瑰 " ; // 生产茎 stem = " 20厘米 " ; // 生产叶子 leaf = " 椭圆形 " ; // 生产花 flower = " 大红大白 " ; } public void create(){ System.out.println(name + " : 茎 " + " - " + stem + " , 叶 " + " - " + leaf + " , 花 " + " - " + flower); } } /** * 场景类 */ public class Client { public static void main(String[] args){ // 开始种玫瑰花 RoseFlowerpot rfp = new RoseFlowerpot(); rfp.grow(); // 盛开 rfp.create(); // 玫瑰 : 茎 - 20厘米 , 叶 - 椭圆形 , 花 - 大红大白 半径5厘米 // 开始种荷花 WaterlilyFlowerpot wf = new WaterlilyFlowerpot(); wf.grow(); // 盛开 wf.create(); // 荷花 : 茎 - 40厘米 , 叶 - 圆形 , 花 - 白里透红 半径10厘米 } }
缺点:
耦合性强,并且有大量代码是重复的。如果想对叶子做一些修改,茎和花的代码也要跟着重写。在这个例子中你可能觉得写一写茎和花的也不费什么事,可真要是想写出像图片中那么漂亮的鲜花的话,每一部分的代码都是很多的,并且这些代码都放在在盆景类中,会让盆景这个类显得很臃肿。那么怎么改?
3.归纳阶段:
耦合性强就要解耦,代码臃肿就要简化和分离。我们需要将盆景这个复杂的类分解成相对简单的类,比如将花盆和鲜花分离,使得同样的花盆可以生长出不同的鲜花,然后再将鲜花分成几个简单的类,使得某一部分的修改不影响其他部分;这也就是生成器模式。 其定义:Separate the construction of a complex object from its representation so that the same construction process can create different representations.(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)
结构类图:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
/** * 花朵的茎 */ public class Stem { private String name = " 茎 " ; private String length; public Stem(){ this .length = " 5厘米 " ; } public Stem(String length){ this .length = length; } public String getName() { return name; } public String getLength() { return length; } } /** * 叶子 */ public class Leaf { private String name = " 叶 " ; private String shape; public Leaf(String shape){ this .shape = shape; } public Leaf(){ this .shape = " 圆形 " ; } public String getName() { return name; } public String getShape() { return shape; } } /** * 花 */ public class Flower { private String name = " 花 " ; private String color; private String radius; public Flower(){ this .color = " 大红大白 " ; this .radius = " 5厘米 " ; } public Flower(String color,String radius){ this .color = color; this .radius = radius; } public String getName() { return name; } public void setName(String name) { this .name = name; } public String getRadius() { return radius; } public String getColor() { return color; } } /** * 以下属性应该为私有,设为公有纯粹是为了方便说明问题并减少代码量 * @author 谭鹏飞 * */ public abstract class Seed { public String name; // 茎 public Stem stem; // 叶 public Leaf leaf; // 花 public Flower flower; public abstract void grow(); } /** * 玫瑰类 */ public class Rose extends Seed{ public Rose(Stem stem,Leaf leaf,Flower flower){ // 说明种类 name = " 玫瑰 " ; // 生产茎 this .stem = stem; // 生产叶子 this .leaf = leaf; // 生产花 this .flower = flower; } public Rose(Stem stem){ this (stem, new Leaf(), new Flower()); // 说明种类 name = " 玫瑰 " ; } public Rose(){ this ( new Stem(), new Leaf(), new Flower()); // 说明种类 name = " 玫瑰 " ; } public void grow(){ System.out.println(name + " : " + stem.getName() + " - " + stem.getLength() + " , " + leaf.getName() + " - " + leaf.getShape() + " , " + flower.getName() + " - " + flower.getColor() + " 半径 " + flower.getRadius()); } } /** * 场景类 */ public class Client { public static void main(String[] args) { // TODO Auto-generated method stub Seed rose = new Rose(); Soil soil = new Soil(rose); soil.create(); // 玫瑰 : 茎 - 5厘米 , 叶 - 圆形 , 花 - 大红大白 半径5厘米 } }
设计体会:
世界上没有两片完全相同的树叶,将构建具体树叶的细节与构建树的表示分离,从而避免了为修改一片树叶而重写了一棵树的麻烦!
4.验证阶段
让上例中的玫瑰的茎再长高5厘米,而不改动叶子和花部分的代码。除场景类外,其他类均不变化,重复代码不再赘述。
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
/** * 场景类 */ public class Client { public static void main(String[] args) { // 如果你想将花朵长高一点,其它部分不变,没问题,而且改动也不多 Stem stem = new Stem( " 10厘米 " ); Seed tallrose = new Rose(stem); soil = new Soil(tallrose); soil.create(); // 玫瑰 : 茎 - 10厘米 , 叶 - 圆形 , 花 - 大红大白 半径5厘米 } }
5.抽象描述
思路描述:
该模式的核心就是分离细节、推迟细节的现实。上面用类来实现细节的分离只是一个小例子 ,你也可以用抽象方法,将细节推迟到子类实现等。不管你用什么方法分离出了细节,再组合回来的时候,你又可以增加许多的操作,比如各个部分的比例、顺序等。生成器模式本身需要和其他模式结合使用,最经常结合的就是模板模式(用于生成具体的子类),其他要根据实际情况而定。
类结构图: