設計模式——工廠方法模式

《Head First設計模式》筆記整理...歡迎交流...編程

定義

定義了一個建立對象的接口,但由子類決定要實例化的類是哪個。工廠方法讓類把實例化推遲到子類。

OO原則

  • 封裝變化
  • 多用組合少用繼承
  • 針對接口變成,不針對實現編程
  • 爲交互對象之間的鬆耦合設計而努力
  • 類應該對擴展開放,對修改關閉
  • 要依賴抽象,不要依賴具體類

類圖

圖片描述

正如在正式定義中所說的,經常聽到其餘開發人員說,工廠方法讓子類決定要實例化的類是哪個。但願不要理解錯誤,所謂的「決定」,並非指模式容許子類自己在運行時作決定,而是指在編寫建立者類時,不須要知道實際建立的具體產品是哪個。選擇使用哪一個產品的子類,天然就決定看實際建立的產品是什麼。設計模式

依賴倒置原則

要依賴抽象,不要依賴具體類。

這個原則聽起來很像「針對接口編程,不針對實現編程」。然而,這裏更強調「抽象」。這個原則說明了不能讓高層組件依賴低層組件,「二者」都應該依賴抽象。測試

clipboard.png

幾個方法幫助你遵循此原則......this

  • 變量不能夠持有具體類的引用
  • 不要讓類派生自具體類
  • 不要覆蓋積累中已經實現的方法

若是覆蓋基類已經實現的方法,那麼你的基類不是一個真正適合被繼承的抽象。基類中已經實現的方法,應該由全部的子類共享。spa

須要注意的是,全部的原則都是爲了更好的設計,並非必須隨時都遵循的。設計

建立一個pizza工廠

public abstract class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza;
        
        pizza = ceratePizza(type);
        
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        
        return pizza;
    }
    
    public abstract Pizza createPizza(String type);
    
    //其它方法
}


public class NYPizzaStore extends PizzaStore {
    Pizza createPizza(String item) {
        if(item.eauals(cheese)) {
            return new NYStyleCheesePizza();
        } else if() {
            ...
        }
    }
}
//工廠方法是抽象的,因此必須依賴子類來處理對象的建立
//工廠方法必須返回一個產品
//工廠方法將客戶,和實際建立具體產品的代碼分隔開來
//工廠方法可能須要傳遞參數(也可能不須要)來指定所須要的產品

abstract Product factoryMethod(String type)
public abstract class Pizza {
    String name;
    String dough;
    String sauce;
    ArrayList topppings = new ArrayList();
    
    void prepare() {
        
        ...
        
        for(int i = 0; i < topppings.size(); i++) {
            System.out.printIn("  " + topppings.get(i)); //準備工做要以特定的順序進行,有一道連串的步驟
        }
    };
    
    void brake() { ... };
    
    void cut() { ... };
    
    void box() { ... };
    
    Public String getName() {
        return name;
    };
}

public NYStyleCheesePizza extends Pizza {
    public NYStyleCheesePizza() {
        name = "NY Style Suace and Cheese Pizza";
        dough = "Thin Crust Dough";
        sauce = "Marinara Sauce";
        
        topppings.add("Grated Reggiao Cheese");
    }
}

測試code

public class PizzaTestDrive {
    public static void main() {
        PizzaStore nyStore = NyPizzaStore();
        Pizza pizza = nyStore.orderPizza("cheese");
        
        System.out.printIn("Ethan ordered a " + pizza.getName() + "\n");
        // Ethan ordered a NY Style Suace and Cheese Pizza
    }
}

抽象工廠模式

抽象工廠模式提供一個接口,用於建立相關或依賴對象的家族,而不準奧明確指定具體類。

抽象工廠容許客戶使用抽象的接口來建立一組相關的產品,而不須要知道(或關心)實際產出的產品是什麼。這樣依賴,客戶就從具體產品中被解耦。對象

再回到披薩店繼承

上面披薩店的設計已經很棒了,可是對不一樣地區的加盟店,,原料是不同的(如,紐約的紅醬料和芝加哥的醬料是不同的),可是流程是一致。如何解耦?建立一個原料工廠。接口

public class NYPizzaStore extends PizzaStore {
    protected Pizza createPizza(Stirng item) {
        Pizza pizza = null;
        PizzaIngredientFactory ingredientFactory = new PizzaIngredientFactory();
    }
    
    if(item.equals("cheese")) {
        pizza = new cheesePizza(ingredientFactory);
        pizza.setName("new You Style Cheese Pizza");
    } else if (...) { ... }
    
    return pizza;
}

public abstract class Pizza {
    String name;
    Dough dough;
    Sauce sauce;
    Veggies veggies();
    chenegie veggues;
    Cheese cheeese;
    Perperroni pepperoni;
    clams clams;
    
    abstract void Prepare();
    
    void bake() { ... }
    
    void cut() { ... }
    
    void box() { ... }
    
    void setName(String name) {}
    
    void setName() {}
}

public class CheesePizza extends Pizza {
    PizzaIngredientFactory ingredientFactory;
    
    public CheesePizza(PizzaIngredientFactory ingredientFactory) {
        this.ingredientFactory = ingredientFactory;
    }
    
    void prepare() {
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
        cheese = ingredientFactory.createCheese();
    }
}
相關文章
相關標籤/搜索