複雜物件的組裝與建立——建造者模式(二)

Liuwei-Sunny發表於2012-04-04

8.3 完整解決方案

      Sunny公司開發人員決定使用建造者模式來實現遊戲角色的建立,其基本結構如圖8-3所示:

8-3 遊戲角色建立結構圖

      在圖8-3中,ActorController充當指揮者,ActorBuilder充當抽象建造者,HeroBuilderAngelBuilderDevilBuilder充當具體建造者,Actor充當複雜產品。完整程式碼如下所示:

//Actor角色類:複雜產品,考慮到程式碼的可讀性,只列出部分成員屬性,且成員屬性的型別均為String,真實情況下,有些成員屬性的型別需自定義

class Actor

{

       private  String type; //角色型別

       private  String sex; //性別

       private  String face; //臉型

       private  String costume; //服裝

       private  String hairstyle; //髮型

      

       public  void setType(String type) {

              this.type  = type;

       }

       public  void setSex(String sex) {

              this.sex  = sex;

       }

       public  void setFace(String face) {

              this.face  = face;

       }

       public  void setCostume(String costume) {

              this.costume  = costume;

       }

       public  void setHairstyle(String hairstyle) {

              this.hairstyle  = hairstyle;

       }

       public  String getType() {

              return  (this.type);

       }

       public  String getSex() {

              return  (this.sex);

       }

       public  String getFace() {

              return  (this.face);

       }

       public  String getCostume() {

              return  (this.costume);

       }

       public  String getHairstyle() {

              return  (this.hairstyle);

       }

}

 

//角色建造器:抽象建造者

abstract class ActorBuilder

{

       protected  Actor actor = new Actor();

      

       public  abstract void buildType();

       public  abstract void buildSex();

       public  abstract void buildFace();

       public  abstract void buildCostume();

       public  abstract void buildHairstyle();

 

    //工廠方法,返回一個完整的遊戲角色物件

       public Actor createActor()

       {

              return actor;

       }

}

 

//英雄角色建造器:具體建造者

class HeroBuilder extends ActorBuilder

{

       public  void buildType()

       {

              actor.setType("英雄");

       }

       public  void buildSex()

       {

              actor.setSex("");

       }

       public  void buildFace()

       {

              actor.setFace("英俊");

       }

       public  void buildCostume()

       {

              actor.setCostume("盔甲");

       }

       public  void buildHairstyle()

       {

              actor.setHairstyle("飄逸");

       }    

}

 

//天使角色建造器:具體建造者

class AngelBuilder extends ActorBuilder

{

       public  void buildType()

       {

              actor.setType("天使");

       }

       public  void buildSex()

       {

              actor.setSex("");

       }

       public  void buildFace()

       {

              actor.setFace("漂亮");

       }

       public  void buildCostume()

       {

              actor.setCostume("白裙");

       }

       public  void buildHairstyle()

       {

              actor.setHairstyle("披肩長髮");

       }    

}

 

//惡魔角色建造器:具體建造者

class DevilBuilder extends ActorBuilder

{

       public  void buildType()

       {

              actor.setType("惡魔");

       }

       public  void buildSex()

       {

              actor.setSex("");

       }

       public  void buildFace()

       {

              actor.setFace("醜陋");

       }

       public  void buildCostume()

       {

              actor.setCostume("黑衣");

       }

       public  void buildHairstyle()

       {

              actor.setHairstyle("光頭");

       }    

}

 

      指揮者類ActorController定義了construct()方法,該方法擁有一個抽象建造者ActorBuilder型別的引數,在該方法內部實現了遊戲角色物件的逐步構建,程式碼如下所示:

//遊戲角色建立控制器:指揮者

class ActorController

{

    //逐步構建複雜產品物件

       public Actor construct(ActorBuilder ab)

       {

              Actor actor;

              ab.buildType();

              ab.buildSex();

              ab.buildFace();

              ab.buildCostume();

              ab.buildHairstyle();

              actor=ab.createActor();

              return actor;

       }

}

       為了提高系統的靈活性和可擴充套件性,我們將具體建造者類的類名儲存在配置檔案中,並通過工具類XMLUtil來讀取配置檔案並反射生成物件,XMLUtil類的程式碼如下所示:

import javax.xml.parsers.*;

import org.w3c.dom.*;

import org.xml.sax.SAXException;

import java.io.*;

class XMLUtil

{

//該方法用於從XML配置檔案中提取具體類類名,並返回一個例項物件

       public  static Object getBean()

       {

              try

              {

                     //建立文件物件

                     DocumentBuilderFactory  dFactory = DocumentBuilderFactory.newInstance();

                     DocumentBuilder  builder = dFactory.newDocumentBuilder();

                     Document  doc;                                                

                     doc  = builder.parse(new File("config.xml"));

             

                     //獲取包含類名的文字節點

                     NodeList  nl = doc.getElementsByTagName("className");

            Node  classNode=nl.item(0).getFirstChild();

            String  cName=classNode.getNodeValue();

           

            //通過類名生成例項物件並將其返回

            Class c=Class.forName(cName);

                 Object obj=c.newInstance();

            return obj;

         }  

         catch(Exception e)

         {

              e.printStackTrace();

              return null;

          }

       }

}

       配置檔案config.xml中儲存了具體建造者類的類名,程式碼如下所示:

<?xml version="1.0"?>

<config>

       <className>AngelBuilder</className>

</config>   

        編寫如下客戶端測試程式碼:

class Client

{

       public  static void main(String args[])

       {

              ActorBuilder ab; //針對抽象建造者程式設計

              ab =  (ActorBuilder)XMLUtil.getBean(); //反射生成具體建造者物件

 

         ActorController ac = new  ActorController();

              Actor actor;

              actor = ac.construct(ab); //通過指揮者建立完整的建造者物件

 

              String  type = actor.getType();

              System.out.println(type  + "的外觀:");

              System.out.println("性別:" + actor.getSex());

              System.out.println("面容:" + actor.getFace());

              System.out.println("服裝:" + actor.getCostume());

              System.out.println("髮型:" + actor.getHairstyle());

       }

}

      編譯並執行程式,輸出結果如下:

天使的外觀:

性別:女

面容:漂亮

服裝:白裙

髮型:披肩長髮

      在建造者模式中,客戶端只需例項化指揮者類,指揮者類針對抽象建造者程式設計,客戶端根據需要傳入具體的建造者型別,指揮者將指導具體建造者一步一步構造一個完整的產品(逐步呼叫具體建造者的buildX()方法),相同的構造過程可以建立完全不同的產品。在遊戲角色例項中,如果需要更換角色,只需要修改配置檔案,更換具體角色建造者類即可;如果需要增加新角色,可以增加一個新的具體角色建造者類作為抽象角色建造者的子類,再修改配置檔案即可,原有程式碼無須修改,完全符合“開閉原則”。

【作者:劉偉 http://blog.csdn.net/lovelion

相關文章