詳解JAVA面向對象的設計模式 (三)、工廠模式

工廠模式 Factory

介紹

工廠模式(Factory Pattern)是 Java 中最經常使用的設計模式之一。這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。html

在工廠模式中,咱們在建立對象時不會對客戶端暴露建立邏輯,而且是經過使用一個共同的接口來指向新建立的對象。java

前言

工廠模式主要分爲三種形式設計模式

  1. 簡單工廠模式(不屬於GoF的23種設計模式中)ide

  2. 工廠方法模式函數

  3. 抽象工廠模式ui

簡單來講,本質上工廠模式是對建立對象過程的一種封裝。經過封裝,讓客戶端無需在乎對象建立的過程和邏輯。看看下面的例子。操作系統

本文部分解釋摘錄自 http://c.biancheng.net/view/1351.html.net

簡單工廠模式

好比咱們去一家餐廳。咱們想要點餐吃飯。設計

那麼能夠看做是客戶獲得了飲料,食物,餐具,而後一一使用。咱們先如下單食物爲例,寫個例子。code

不使用工廠模式時是這樣的

public static void main(String[] args) {
	// 普通建立對象
    Hamburger hamburger = new Hamburger();
    Steak steak = new Steak();
    hamburger.eat();
    steak.eat();
}

然而這樣的建立對象,語義上不清晰且須要在客戶端中初始化對象。

畢竟給咱們製做食物的是餐廳,因此咱們能夠把餐廳理解成一種工廠。咱們客戶向餐廳點單就好了。

簡單工廠模式的結構圖

在例子中實現

首先,餐廳生產的食品Food,均可以食用,建立接口eat。

public interface Food {
    void eat();
}

那麼使用漢堡和牛扒就應該以下實現

public class Hamburger implements Food {
    @Override
    public void eat() {
        System.out.println("吃漢堡,嘎嘎嘎");
    }
}

public class Steak implements Food {
    @Override
    public void eat() {
        System.out.println("吃牛扒,嘎嘎嘎");
    }
}

那麼餐廳,就能夠做爲生產這些產品的工廠

public class RestaurantFactory {
    public Food getFood(String type) {
        if (type == null)
            return null;
        else if (type.equalsIgnoreCase("hamburger"))
            return new Hamburger();
        else if (type.equalsIgnoreCase("steak"))
            return new Steak();
        return null;
    }
}

有了餐廳工廠之後,客戶下單就不須要本身去new食物了。直接問餐廳拿!

public static void main(String[] args) {
        // 普通建立對象
        Hamburger hamburger = new Hamburger();
    	Steak steak = new Steak();
    	hamburger.eat();
    	steak.eat();

        // 利用簡單工廠建立對象
        RestaurantFactory rpf = new RestaurantFactory();
        Food hamburger = rpf.getFood("hamburger");
        Food steak = rpf.getFood("steak");
        hamburger.eat();
        steak.eat();
}

上面是普通建立,下面是簡單工廠建立,最後會輸出2次

吃漢堡,嘎嘎嘎
吃牛排,嘎嘎嘎

上面咱們能夠看到,咱們把建立對象都寫進了一個方法裏。其實咱們也能夠分開寫,一個方法得到一種對象也能夠,看具體需求。

public class RestaurantFactory {
    public Food getHamburger() {
    	return new Hamburger();
    }
    public Food getSteak() {
    	return new Steak();
    }
}

靜態工廠

靜態工廠只是在普通工廠上作一些小小的改變,意味着,工廠裏的建立對象方法改寫爲靜態方法,如此以來,就不須要new Factory 再操做工廠生成對象了。

public class RestaurantFactory {
    public static Food getHamburger() {
    	return new Hamburger();
    }
    public static Food getSteak() {
    	return new Steak();
    } 	
}

public static void main(String[] args) {
        // 利用靜態工廠建立對象
        Food hamburger = RestaurantFactory.getHamburger();
        Food steak = RestaurantFactory.getSteak();
        hamburger.eat();
        steak.eat();
}

簡單工廠模式的缺點

每次須要建立新的對象的時候,就得去修改工廠類,這明顯違背了面向對象設計中的「開閉原則」。

工廠方法模式

工廠方法在簡單工廠上作了抽象處理。

把具體工廠抽象出了一個超級工廠,全部的具體工廠都實現這個抽象的超級工廠。客戶端經過訪問具體工廠的工廠方法來建立產品。

結構

工廠方法模式的主要角色以下。

  1. 抽象工廠(Abstract Factory):提供了建立產品的接口,調用者經過它訪問具體工廠的工廠方法 newProduct() 來建立產品。
  2. 具體工廠(ConcreteFactory):主要是實現抽象工廠中的抽象方法,完成具體產品的建立。
  3. 抽象產品(Product):定義了產品的規範,描述了產品的主要特性和功能。
  4. 具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來建立,它同具體工廠之間一一對應。

工廠方法模式的結構圖

在例子中實現

// 抽象工廠
public abstract class FoodAbstractFactory {
    public abstract Food getFood();
}

// 具體工廠 麥當勞, Hamburger實現Food接口
public class McDonaldFactory extend FoodAbstractFactoty {
    @Override
    public Food getFood() {
        return new Hamburger();
    }
}

// 具體工廠 咖啡廳, Steak實現Food接口
public class CafeFactory extend FoodAbstractFactoty {
    @Override
    public Food getFood() {
        return new Steak();
    }
}

// Main函數
public static void main(String[] args) {
        // 工廠方法建立對象
        FoodAbstractFactory mcDonald = new McDonaldFactory();
    	FoodAbstractFactory cafe = new CafeFactory();
        Food hamburger = mcDonald.getFood();
        Food steak = cafe.getFood();
        hamburger.eat();
        steak.eat();
}

適用場景

工廠方法模式一般適用於如下場景。

  • 客戶只知道建立產品的工廠名,而不知道具體的產品名。如 TCL 電視工廠、海信電視工廠等。
  • 建立對象的任務由多個具體子工廠中的某一個完成,而抽象工廠只提供建立產品的接口。
  • 客戶不關心建立產品的細節,只關心產品的品牌。

優缺點

工廠方法模式的主要優勢有:

  • 用戶只須要知道具體工廠的名稱就可獲得所要的產品,無須知道產品的具體建立過程;
  • 在系統增長新的產品時只須要添加具體產品類和對應的具體工廠類,無須對原工廠進行任何修改,知足開閉原則;

其缺點是:

  • 每增長一個產品就要增長一個具體產品類和一個對應的具體工廠類,這增長了系統的複雜度。

模式的擴展

當須要生成的產品很少且不會增長,一個具體工廠類就能夠完成任務時,可刪除抽象工廠類。這時工廠方法模式將退化到簡單工廠模式

抽象工廠模式

介紹

前面介紹的工廠方法模式中考慮的是一類產品的生產,如畜牧場只養動物、電視機廠只生產電視機、計算機軟件學院只培養計算機軟件專業的學生等。

同種類稱爲同等級,也就是說:工廠方法模式只考慮生產同等級的產品,可是在現實生活中許多工廠是綜合型的工廠,能生產多等級(種類) 的產品,如農場裏既養動物又種植物,電器廠既生產電視機又生產洗衣機或空調,大學既有軟件專業又有生物專業等。

本節要介紹的抽象工廠模式將考慮多等級產品的生產,將同一個具體工廠所生產的位於不一樣等級的一組產品稱爲一個產品族

抽象工廠模式的結構圖

舉例解釋

抽象工廠的意義是確實比較抽象。。。它主要用於建立 對象家族 。下面舉例說明,更好理解它主要解決的問題。

好比我如今手機上安裝了一款App,我想在這個App上實現換膚功能。(包括配色和ui風格)

那麼,咱們就能夠理解爲,換膚功能就是一個抽象工廠,而功能中提供的每一種皮膚,就是一個具體工廠類。

每當咱們修改了皮膚主題,通常都會須要咱們重啓App,因而App會根據已選的皮膚主題,找到對應的具體皮膚主題工廠,進行UI初始化,包括ui配色,button風格,slider特效等等......

在以上的換膚過程裏,咱們能夠發現,皮膚主題工廠最終初始化出來的對象們都是不一樣類的,好比 Color,Button,Slider,Bar,Table。那麼以上這些類實例就能夠看做是主題工廠產生的對象家族

在例子中實現

上面的解釋若是不太明白,就直接看代碼吧。仍是餐廳例子。餐廳除了食物,還會生產飲品,餐具等等。也就是說,食物,飲品和餐具就是餐廳抽象工廠定義的對象家族。看代碼

// 抽象餐廳工廠
public abstract class RestaurantFactory {
    public abstract Food getFood();
    public abstract Drinks getDrinks();
    public abstract Item getItem();
}

// 具體工廠 麥當勞, Hamburger實現Food接口,Cock實現Drinks,Tissue實現Item
public class McDonaldFactory extend FoodAbstractFactoty {
    @Override
    public Food getFood() {
        return new Hamburger();
    }
    @Override
    public Drinks getDrinks() {
        return new Cock();
    }
    @Override
    public Item getItem() {
        return new Tissue();
    }
}

// 具體工廠 咖啡廳, Steak實現Food接口,Coffee實現Drinks,Knife實現Item
public class CafeFactory extend FoodAbstractFactoty {
    @Override
    public Food getFood() {
        return new Steak();
    }
    @Override
    public Drinks getDrinks() {
        return new Coffee();
    }
    @Override
    public Item getItem() {
        return new Knife();
    }
}

// Main函數
public static void main(String[] args) {
        // 抽象工廠建立對象
        FoodAbstractFactory mcDonald = new McDonaldFactory();
    	FoodAbstractFactory cafe = new CafeFactory();
        Food hamburger = mcDonald.getFood();
    	Drinks cock = mcDonald.getDrinks();
    	Item tissue = mcDonald.getItem();
        Food steak = cafe.getFood();
    	Drinks coffee = cafe.getDrinks();
    	Item knife = cafe.getItem();
        hamburger.eat();
        steak.eat();
	cock.drink();
    	coffee.drink();
    	tissue.use();
    	knift.use();
}

模式的應用場景

抽象工廠模式最先的應用是用於建立屬於不一樣操做系統的視窗構件。如 java 的 AWT 中的 Button 和 Text 等構件在 Windows 和 UNIX 中的本地實現是不一樣的。

抽象工廠模式一般適用於如下場景:

  1. 當須要建立的對象是一系列相互關聯或相互依賴的產品族時,如電器工廠中的電視機、洗衣機、空調等。
  2. 系統中有多個產品族,但每次只使用其中的某一族產品。若有人只喜歡穿某一個品牌的衣服和鞋。
  3. 系統中提供了產品的類庫,且全部產品的接口相同,客戶端不依賴產品實例的建立細節和內部結構。

模式的擴展

抽象工廠模式的擴展有必定的「開閉原則」傾斜性:

  1. 當增長一個新的產品族時只需增長一個新的具體工廠,不須要修改原代碼,知足開閉原則
  2. 當產品族中須要增長一個新種類的產品時,則全部的工廠類都須要進行修改,不知足開閉原則

另外一方面,當系統中只存在一個等級結構的產品時,抽象工廠模式將退化到工廠方法模式。

相關文章
相關標籤/搜索