熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

深入淺出基於Java的建造設計模式

2013-11-23 19:45:50  來源: Java高級技術 

  引子
  前幾天陪朋友去裝機店攢了一台電腦看著裝機工在那裡熟練的裝配著機器不禁想起來了培訓時講到的建造模式作為裝機工他們不用管你用的CPU是Intel還是AMD也不管你的顯卡是千大元還是白送的都能三下五除二的裝配在一起——一台PC就誕生了!當然對於客戶來說你也不知道太多關於PC組裝的細節這和建造模式是多麼的相像啊!
  
  今天就來探討一下建造模式
  
  定義與結構
  GOF給建造模式的定義為將一個復雜對象的構建與它的表示分離使得同樣的構建過程可以創建不同的表示可以將建造模式的精髓概括為將構造復雜對象的過程和對象的部件解耦這是對降低耦合提高可復用性精神的一種貫徹其實這種精神貫徹在GOF幾乎所有的設計模式中
  
  是不是和上面提到的裝機流程相像?
  
  這個很多人認為同抽象工廠模式相似的建造模式用在什麼樣的設計環境下呢(對於兩者的比較稍候討論)?我認為可以總結為以下環境當要生成的產品有復雜的內部結構其中的內部結構由多個對象組成系統將來可能要改變產品對象的內部結構的構成或者實現方式比如說產品的一些屬性現在是從數據庫中得到的而將來可能從XML中解析得到而且不能將產品的內部構造完全暴露給客戶程序一是為了可用性二是為了安全等因素滿足上面的設計環境就可以考慮使用建造模式來搭建框架了 來看看建造模式的組成吧
  
  抽象建造者角色這個角色用來規范產品對象的各個組成成分的建造一般而言此角色獨立於應用程序的商業邏輯
  
  具體建造者角色擔任這個角色的是於應用程序緊密相關的類它們在指導者的調用下創建產品實例這個角色在實現抽象建造者角色提供的方法的前提下達到完成產品組裝提供成品的功能
  
  指導者角色調用具體建造者角色以創建產品對象指導者並沒有產品類的具體知識真正擁有產品類的具體知識的是具體建造者對象 產品角色建造中的復雜對象它要包含那些定義組件的類包括將這些組件裝配成產品的接口
  
  來看下這些角色組成的類圖
  
  首先客戶程序創建一個指導者對象一個建造者角色並將建造者角色傳入指導者對象進行配置然後指導者按照步驟調用建造者的方法創建產品最後客戶程序從建造者或者指導者那裡得到產品
  
  從建造模式的工作流程來看建造模式將產品的組裝外部化到了建造者角色中來這是和任何正規的工廠模式不一樣的——產品的創建是在產品類中完成的
  
  實現
  實在找不到太好的例子我認為《java與模式》中發郵件的例子還算可以這裡我將《Think in Patterns with Java》中的例子放到這裡權且充個門面媒體可以存在不同的表達形式比如書籍雜志和網絡這個例子表示不同形式的媒體構造的步驟是相似的所以可以被提取到指導者角色中去
  
  import javautil*;
  import junitframework*;
  
  //不同的媒體形式:
  
  class Media extends ArrayList {}
  class Book extends Media {}
  class Magazine extends Media {}
  class WebSite extends Media {}
  
  // 進而不含不同的媒體組成元素:
  
  class MediaItem {
  private String s;
  public MediaItem(String s) { thiss = s; }
  public String toString() { return s; }
  }
  
  class Chapter extends MediaItem {
  public Chapter(String s) { super(s); }
  }
  
  class Article extends MediaItem {
  public Article(String s) { super(s); }
  }
  
  class WebItem extends MediaItem {
  public WebItem(String s) { super(s); }
  }
  
  // 抽象建造者角色它規范了所有媒體建造的步驟:
  
  class MediaBuilder {
  public void buildBase() {}
  public void addMediaItem(MediaItem item) {}
  public Media getFinishedMedia() { return null; }
  }
  
  //具體建造者角色
  
  class BookBuilder extends MediaBuilder {
  private Book b;
  public void buildBase() {
  Systemoutprintln(Building book framework);
  b = new Book();
  }
  
  public void addMediaItem(MediaItem chapter) {
  Systemoutprintln(Adding chapter + chapter);
  badd(chapter);
  }
  public Media getFinishedMedia() { return b; }
  }
  
  class MagazineBuilder extends MediaBuilder {
  private Magazine m;
  public void buildBase() {
  Systemoutprintln(Building magazine framework);
  m = new Magazine();
  }
  
  public void addMediaItem(MediaItem article) {
  Systemoutprintln(Adding article + article);
  madd(article);
  }
  public Media getFinishedMedia() { return m; }
  }
  
  class WebSiteBuilder extends MediaBuilder {
  private WebSite w;
  public void buildBase() {
  Systemoutprintln(Building web site framework);
  w = new WebSite();
  }
  
  public void addMediaItem(MediaItem webItem) {
  Systemoutprintln(Adding web item + webItem);
  wadd(webItem);
  }
  
  public Media getFinishedMedia() { return w; }
  }
  
  //指導者角色也叫上下文
  class MediaDirector {
  private MediaBuilder mb;
  public MediaDirector(MediaBuilder mb) {
  thismb = mb; //具有策略模式相似特征的
  }
  
  public Media produceMedia(List input) {
  mbbuildBase();
  for(Iterator it = erator(); ithasNext();)
  mbaddMediaItem((MediaItem)itnext());
  return mbgetFinishedMedia();
  }
  };
  
  //測試程序——客戶程序角色
  
  public class BuildMedia extends TestCase {
  private List input = ArraysasList(new MediaItem[] {
  new MediaItem(item) new MediaItem(item)
  new MediaItem(item) new MediaItem(item)
  });
  
  public void testBook() {
  MediaDirector buildBook = new MediaDirector(new BookBuilder());
  Media book = buildBookproduceMedia(input);
  String result = book: + book;
  Systemoutprintln(result);
  assertEquals(result book: [item item item item]);
  }
  
  public void testMagazine() {
  MediaDirector buildMagazine = new MediaDirector(new MagazineBuilder());
  Media magazine = buildMagazineproduceMedia(input);
  String result = magazine: + magazine;
  Systemoutprintln(result);
  assertEquals(result magazine: [item item item item]);
  }
  
  public void testWebSite(){
  MediaDirector buildWebSite = new MediaDirector(new WebSiteBuilder());
  Media webSite = buildWebSiteproduceMedia(input);
  String result = web site: + webSite;
  Systemoutprintln(result);
  assertEquals(result web site: [item item item item]);
  }
  
  public static void main(String[] args) {
  junittextuiTestRunnerrun(BuildMediaclass);
  }
  
  }
  
  在實現的時候抽象建造角色提供的接口必須足夠普遍以適應不同的具體建造角色對於一個建造角色來說可能某個步驟是不需要的可以將此接口實現為空多個產品之間可能沒有太多的共同點可以提供一個標示接口作為抽象產品角色也可以不提供抽象產品角色這時要將提供產品的接口從抽象建造角色裡面去掉不然就會編譯出問題
  
  應用優點
  建造模式可以使得產品內部的表象獨立變化在原來的工廠方法模式中產品內部的表象是由產品自身來決定的而在建造模式中則是外部化為由建造者來負責這樣定義一個新的具體建造者角色就可以改變產品的內部表象符合開閉原則
  
  建造模式使得客戶不需要知道太多產品內部的細節它將復雜對象的組建和表示方式封裝在一個具體的建造角色中而且由指導者來協調建造者角色來得到具體的產品實例
  
  每一個具體建造者角色是毫無關系的
  
  建造模式可以對復雜產品的創建進行更加精細的控制產品的組成是由指導者角色調用具體建造者角色來逐步完成的所以比起其它創建型模式能更好的反映產品的構造過程
  
  擴展
  建造模式中很可能要用到組成成品的各種組件類對於這些類的創建可以考慮使用工廠方法或者原型模式來實現在必要的時候也可以加上單例模式來控制類實例的產生但是要堅持一個大前提就是要使引入的模式給你的系統帶來好處而不是臃腫的結構 建造模式在得到復雜產品的時候可能要引用多個不同的組件在這一點上來看建造模式和抽象工廠模式是相似
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27421.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.