跳到主要內容

發表文章

目前顯示的是 6月, 2016的文章

命令模式 (Command Pattern)

         今天有一家家電廠商,想請你設計一個控制家電自動化的遙控器。遙控器上有多個插槽可控制不同家電,每個家電在遙控器上要提供開、關按鈕。廠商已提供控制家電的 API,你只需要設計遙控器 API,可以控制不同家電。注意未來可能會有新的家電。         看起來好像不好設計。既要能控制現在的家電,還要能滿足擴充性,以便控制新的家電。最重要的是,要怎麼讓「遙控器」和「家電」之間能夠鬆綁呢?有沒有一個設計模式,可以讓 「發出需求的物件」 和 「接受與執行需求的物件」 分割開呢?這時候就是命令模式派上用場的時候了。使用命令模式,遙控器只要發出需求,如開電燈,遙控器不用知道到底是誰,做了什麼事,遙控器只知道有發出需求。而需求發出後,就是接收者,電燈,去執行需求,如打開電燈。只看文字可能不是很清楚,直接用程式碼來熟悉吧。         首先我們要先有一個通用的命令介面,以便讓所有家電實做。將來遙控器也是直接對這個通用介面操作即可。 public interface Command { // 很簡單的範例,只要一個執行方法 public void execute(); }         接下來假設想實踐一個打開電燈的命令,假設廠商提供的電燈 API 裡有 on(),off(): public class LightOnCommand implements Command { // 這是廠商提供的,也是實際上處理需求的接收者 private Light mLight; // 傳入實際的電燈讓此命令能控制 // 一旦呼叫了 execute,就由此電燈物件 // 成為接收者,負責處理需求 public LightOnCommand(Light light) { mLight = light; } @Override public void execute() { // 接收者處理需求 // 此例是電燈打開,所以呼叫on() mLight.on(); } }         同理我們也可以設計出很多命令,如電燈關,風扇開、關,門開、關等命令。有了這些命令後,就可以接著

獨體模式 (Singleton Pattern)

        單看名稱就很好理解的設計模式,就是只能有一個且是唯一實體的物件。有些時候最好讓物件只能有一個以避免程式出錯,例如負責處理使用者登入的物件,假如不是獨體模式的話,登入物件就可能有多個,使用者就可能同時登入很多次。         設計此模式的想法也很簡單,不要讓別人能用 new 來建立物件就好,也就是建構子不能宣告為 public。因為其他人不能使用 private 建構子,只能在類別內使用…說那麼多,直接看程式碼比較快: public class Singleton { // 利用一個靜態變數記綠 Singleton 的實體 private static Singleton sInstance; // 可以宣告其他需要的成員變數 // 建構式宣告為 private, 這樣只有在 // Singleton 類別內才能使用 private Singleton(){} // 公開的靜態方法, 其他人要取得物件只能使用此方法 public static Singleton getInstance() { // 不為 null, 表示之前曾建立過, 不用再 new 一次 if(sInstance == null) { // 需要時才建立物件, 稱為 lazy instantiaze sInstance = new Singleton(); } return sInstance; } }         以上就是最基本的獨體模式,接下來來看一下正式定義及類別圖: 獨體模式確保一個類別只有一個實體,並給它一個存取的全域點(global point) Ensure a class has only one instance and provide a global point of access to it.         定義及實作上看起來雖然簡單,但在實務上可能會遇到問題。以上面的程式碼來看,是否真的只會有一個且唯一的物件呢 ? 以多執行緒的角度來看就可以知道,是有可能產生多個物件的,解決方法也不難,

工廠模式 - 抽象工廠模式 (Abstract Factory Pattern)

        延續前一篇 工廠方法模式 ,我們可以有多間加盟店,並且照著固定的 SOP 製作 pizza,加盟店只要專心處理 createPizza() 就好。最後還差一個步驟就能讓我們的 pizza 店更好,就是對 pizza 原料的控管。每個地區會有不同的原料,如何依照不同地區給予不同原料呢?要什麼原料就多一個工廠方法是個不錯的方法,既然會有很多原料工廠方法的話,把它們全集中在一起呢?這就是抽象工廠的概念了。我們可以先定一個抽象的原料工廠: public interface PizzaIngredientFactory { // 每個原料都是一個類別,每個原料都有一個 // 對應的方法建立該原料 public Sauce createSauce(); public Cheese createCheese(); public Vaggies createVaggies(); }         假如每個工廠的實體(子類別)都有一種通用的機制要實作,例如都要先檢查原料,清洗原料之類的,上面的例子也可以改成抽象類別。         我們接下來就可以實作紐約風的原料工廠: // 對於所有原料,紐約原料工廠都提供了紐約的版本 public class NYPizzaIngredientFactory implements PizzaIngredientFactory { @Override public Sauce createSauce() { return new NYSauce(); } @Override public Cheese createCheese() { return new NYCheese(); } @Override public Veggies createVeggies() { return new NYVeggies(); } }         接下來要修改 Pizza,讓它只使用工廠產生出來的產料: public abstract class Pizza { String name; Sauce s