生成器模式(又名建造者模式、Builder Pattern)

作者: 天津城建學院軟件工程  來源: 博客園  發布時間: 2010-12-05 15:39  閱讀: 1922 次  推薦: 0   原文鏈接   [收藏]  

  模式名稱:生成器模式

  1.問題描述

  生活場景:你玩過種地、種花等類似的游戲嗎?這是最近很流行的游戲喲!下面就是從種花游戲中剪切的四個花盆(盆景),很漂亮吧!你將不同的種子放入花盆,一段時間后你就可以看到各種美麗的鮮花了,不同種子所生產出來的鮮花有不同的花朵、葉子和枝莖。編碼該如何實現呢?

                          

  設計目標:將種子放入花盆,一段時間后就可以收獲美麗的鮮花! 

  2.不假思索的思路:將盆景看做一個類,有幾個盆景我new幾個對象,直接完成這一奇妙過程。

  設計類圖:

                      

 
/**
* 荷花盆景
*/
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.(將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。)

  結構類圖:

 
/**
* 花朵的莖

*/
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厘米,而不改動葉子和花部分的代碼。除場景類外,其他類均不變化,重復代碼不再贅述。

 
/**
* 場景類
*/
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.抽象描述

  思路描述:

  該模式的核心就是分離細節、推遲細節的現實。上面用類來實現細節的分離只是一個小例子 ,你也可以用抽象方法,將細節推遲到子類實現等。不管你用什么方法分離出了細節,再組合回來的時候,你又可以增加許多的操作,比如各個部分的比例、順序等。生成器模式本身需要和其他模式結合使用,最經常結合的就是模板模式(用于生成具體的子類),其他要根據實際情況而定。

  類結構圖:

                                     

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()