designPattern

Design Pattern(13) - Facade

以下文章是閱讀 深入淺出Design Pattern 還有 聖經還有Source making的筆記 圖片截圖自lynda.com的Foundations of Programming: Design Patterns 要更深入的理解一定要去看這兩本書

Gatsby

我的好朋友Gatsby 很喜歡開宴會 他喜歡開宴會的原因不是因為他愛玩 而是因為他最心愛的女人就住在他豪宅對面 他總是希望用全天空的煙花 換得佳人的傾城一盼

Alt text Alt text

但每次要開party的時候 Gatsby都會手忙腳亂 因為有太多事情要做

開燈 開噴水池 放音樂 開香檳 放煙火

public class Lights {
  public Lights() {}
  public void on() {
    System.out.println("Light on");
  }
  public void off() {
    System.out.println("Light off");
  }
  public void dim(int level) {
    System.out.println("Light dimming to " + level  + "%");
  }
}
public class Fountain {
  public Fountain(){}
  public void on() {
    System.out.println("Fountain on");
  }
  public void off() {
    System.out.println("Fountain off");
  }
}
public class MusicPlayer {
  public MusicPlayer() {
  }
  public void on() {
    System.out.println("MusicPlayer on");
  }
  public void off() {
    System.out.println("MusicPlayer off");
  }
  public void play() {
    System.out.println("MusicPlayer playing");
  }
  public void pause() {
    System.out.println("MusicPlayer paused");
  }
}
public class Champagne {
  public Champagne() {}
  public void on() {
    System.out.println("Champagne on");
  }

  public void discard() {
    System.out.println("Champagne discard");
  }
}
public class Firework {
  public Firework() {}
  public void setOff() {
    System.out.println("Firework shooting");
  }
}
public class GatsbyParty {
  public static void main(String[] args) {
    MusicPlayer musicplayer = new MusicPlayer();
    Lights lights = new Lights();
    Firework firework = new Firework();
    Fountain fountain = new Fountain();
    Champagne champagne = new Champagne();
    
    partyMode(musicplayer, lights, firework, fountain, champagne);

  }
  private static void partyMode(
      MusicPlayer musicplayer,
      Lights lights,
      Firework firework,
      Fountain fountain,
      Champagne champagne
  ){
    musicplayer.on();
    lights.dim(50);
    fountain.on();
    champagne.on();
    firework.setOff();
  }
}

Welcome to the party! Alt text

但這麼多步驟實在太麻煩了 所以Gatsby請他的好朋友蜘蛛人Nick在拯救世界之後來幫個忙

Alt text

在幫忙的過程中 Nick見到了Gatsby魂牽夢繫的Daisy

Alt text

他說你任何為人稱道的美麗

不及他第一次遇見你

                                                             南山南




Nick幫忙介紹Daisy給Gatsby 度過了不少快樂時光

上面那個片段絕對是影史上前幾名的片段 所有台詞跟歌詞完美穿插 Gatsby跟Daisy介紹 Daisy的讚嘆之詞 管家的回答 每一句都精準的搭配音樂 史上唯一影片用聽的比用看的更加精彩

雖然玩得很開心 但每次開趴都有太多步驟 Nick身為一個認真的工程師 每天都有follow jyt0532的blog 他想起了可以用Facade模式來包裝複雜的subsystem

建一個class 把剛剛那些所有複雜的操作包在一起 當然constructor要把需要操作的物件給進來

public class PartyFacade {
  Lights lights;
  Firework firework;
  Fountain fountain;
  Champagne champagne;
  MusicPlayer musicPalayer;

  public PartyFacade(MusicPlayer musicPalayer,
    Lights lights,
    Firework firework,
    Fountain fountain,
    Champagne champagne) {
    this.firework = firework;
    this.fountain = fountain;
    this.champagne = champagne;
    this.lights = lights;
    this.musicPalayer = musicPalayer;
  }

  public void partyStart() {
    System.out.println("Get ready for a party");
    musicPalayer.on();
    lights.dim(50);
    fountain.on();
    champagne.on();
    firework.setOff();
  }
}

那我的好朋友應該怎麼call呢

PartyFacade party = new PartyFacade(musicplayer, lights, firework, fountain, champagne);
party.partyStart();

這就是最簡單的設計模式

外觀模式

提供一個高層次的統一介面 存取subsystem的一群介面

外觀模式結構

Alt text

優缺點

1.使用子系統更加容易 子系統跟客戶關聯性降低

2.提供了一個訪問子系統的接口 你還是可以直接訪問子系統的任何人

3.子系統增加新的類別可能需要修改外觀類別 違反開閉原則

認識極少化(Least Knowledge Principle)

當你正在設計一個系統 每一個類別 都要注意會跟他互動的類別有哪些 並了解彼此怎麼互動

這個守則的中心思想 是不要讓太多的類別被捆綁在一起 這樣修改某一個類別的時候就不會影響其他人

先來看個例子

public float getTemperature() {
        return station.getThermometer().getTemperature();
}

我們從氣象站先拿到溫度計 再從溫度計拿到溫度 這樣我們需要多依賴Thermometer類別 這樣要是溫度計壞了或 是氣象站壞了 你都會跟著壞

就如同Gatsby不希望依賴太多人 我也認識Nick但我不認識Daisy 所以要是Gatsby透過我再透過Nick才能跟Daisy碰面 依賴太多人了 所以Gatsby直接找Nick介紹Daisy 這就是認識極少化原則

有關認識極少化 比較具體的建議是 如果你要在一個class裡面的functionA中 call別的functionB 那這個別的functionB 必須是

1.這個class本身 的方法

2.這個class的成員 的方法

3.呼叫functionA時丟進來的參數 的方法

4.在functionA裡建立的物件 的方法

相當嚴格 再來個例子

public class Car
{
  Engine engine;

  public void updateDashboardDisplay() {
    //update
  };

  public void start(Key key) {
    Doors doors = new Doors();
    boolean authorized = key.turn(); //呼叫functionA時丟進來的參數 的方法

    if(authorized) {
      engine.start(); //這個class的成員 的方法
      updateDashboardDisplay(); //這個class本身 的方法
      doors.lock(); //在functionA裡建立的物件 的方法
    }
  }
}

上面的四個方法 都沒有違背認識極少化原則

Prologue of Epilogue

煙花易冷 人事易分

當Daisy開車撞死人的時候 Gatsby幫她頂罪 這件事只有我跟Nick知道

Alt text

而最後Gatsby為了心愛的女人 慘死槍下 英年早逝

Daisy還是跟Tom遠走高飛 如同Daisy曾說 「一個女孩在這個世界上最好的生存方式,就是當一個美麗的小傻瓜」

Alt text

那些他曾經款待的宴客 沒有一個來弔唁

Alt text

醜聞滿佈 孤獨死去

紐約已成鬼城 Nick看破美國夢 離開紐約

後記

之前我一直避而不談Gatsby的事 因為我覺得太過沈重 我不喜歡只能從結局開始述說的故事 即使喪禮上只有我跟Nick 我並不為我的好友感到生氣或可惜 我知道這次即使是不歸路 都沒有人能拉住他了 為一個傾國傾城

Gatsby沒有錯 他選擇和愛人活在他構築的完美世界 用生命做了場豪賭 Daisy沒有錯 因為她沒有勇氣和愛人共同面對可能的黑暗 他選擇回到她安全的巢 他們兩個都沒有錯 經典註定要是悲劇

當我收到Nick寄來的包裹 已經是Gatsby死後4年 外面下著大雨 時間是清晨兩點 原來是Nick把他的新書寄給我 我的好友Nick把Gatsby的故事寫成了全美的暢銷小說《The Great Gatsby》 小說的最後一段旁白已經成為了美國小說史上最漂亮的結尾

He had come a long way to this blue lawn, and his dream must have seemed so close that he could hardly fail to grasp it. He did not know that it was already behind him, somewhere back in that vast obscurity beyond the city, where the dark fields of the republic rolled on under the night. Gatsby believed in the green light, the orgastic future that year by year recedes before us. It eluded us then, but that’s no matter—tomorrow we will run faster, stretch our arms further . . . And one fine morning— So we beat on, boats against the current, borne back ceaselessly into the past.

他歷經千山萬水 他的夢想看起來唾手可得 沒有理由再會擦肩而過 但他並不知道 兩人間的機緣已成過去 Gatsby信仰的那道綠光 正向歡愉的未來 在我們眼前 一年年退去 他躲開了我們 但是沒關係 明天我們將跑得更快 手臂將伸得更長 總會有個清朗的早晨 我們會揚帆前進 逆水行舟 但浪潮 卻是奔流不歇 不斷將我們推回過去

Alt text