天天看點

Java設計模式之工廠模式

工廠模式

背景:

一般在程式過程中,利用new來建立對象的時候,也就是在具體化一個類。我們一直所提倡的就是針對接口程式設計,這樣就可以讓程式不用依賴于具體類的實作,而在運作中動态的綁定來實作多态功能。如果代碼是針對接口而寫的,那麼通過多态,它可以與任何新類實作該接口。但是倘若代碼使用大量的具體類的時候,就不利于維護,一旦加入新的具體類的時候,就要修改代碼。

一般建立新對象最簡單的辦法是使用new關鍵字和具體類。隻有在某些場合下,倘若要根據具體的條件來建立不同的類,則此時就需要一個專門用于建立和維護對象的工廠。

工廠模式分為三類:

1)簡單工廠模式(Simple Factory):不利于産生系列産品,也就是不利于多種類型産品。它主要是在基類由一個對象變量負責執行個體化所有的具體類,而這些具體類都屬于一個相同的類型。

2)工廠方法模式(Factory Method):又稱為多形性工廠。它的定義為:定義了一個建立對象的接口或抽象類,但由子類來決定要執行個體化的類是哪一個。工廠方法讓類把執行個體化推遲到了子類中。它通過繼承父類,在子類中決定建立哪些執行個體化類。它主要用在當一個類有多個子類,而每一個子類又同時有各自專屬的子類,則此時就可以用。

3)抽象工廠模式(Abstract Factory):又稱它的定義為:提供了一個借口,用于建立相關或依賴對象的家族,而不需要明确指定具體的類。為工具箱,産生産品族,但不利于産生新的産品;

一 簡單工廠模式

簡單工廠模式又稱靜态工廠方法模式。它存在的目的很簡單:定義一個用于建立對象的接口。

在簡單工廠模式中,一個工廠類處于對産品類執行個體化調用的中心位置上,它決定哪一個産品類應當被執行個體化。

簡單工廠模式主要就是在定義了一個工廠對象變量作為類的字段,來産生對象。

先來看看它的組成:

1) 工廠類角色:這是本模式的核心,含有一定的商業邏輯和判斷邏輯。在java中它往往由一個具體類實作。

2) 抽象産品角色:它一般是具體産品繼承的父類或者實作的接口。在java中由接口或者抽象類來實作。

3) 具體産品角色:工廠類所建立的對象就是此角色的執行個體。在java中由一個具體類實作。

這三種模式從上到下逐漸抽象,并且更具一般性。在簡單工廠中,工廠是另一個類的成員變量。

具體說明:

一個pizza店,可以根據客戶的點單而生産不同的Pizza

生産pizza店:

package com.whut.singleton;

//簡單工廠模式

public class PizzaStore {

SimplePizzaFactory factory;

public PizzaStore(SimplePizzaFactory factory)

{

this.factory=factory;

}

public Pizza orderPizza(String type)

Pizza pizza;

//隻能建立某一個類型下的子類

pizza=factory.createPizza(type);

pizza.prepare();

pizza.bake();

pizza.cut();

pizza.box();

return pizza;

建立Pizza對象的工廠:

import com.whut.factory.NYStyleCheesePizza;

import com.whut.factory.NYStyleClamPizza;

import com.whut.factory.NYStyleVeggiePizza;

import com.whut.factory.Pizza;

public class SimplePizzaFactory {

public Pizza createPizza(String item)

Pizza pizza=null;

// TODO Auto-generated method stub

if(item.equals("cheese"))

pizza= new NYStyleCheesePizza();

elseif(item.equals("veggie"))

pizza= new NYStyleVeggiePizza();

else

pizza= new NYStyleClamPizza();

二 工廠方法模式

工廠方法讓子類決定要執行個體化的是哪個類,這裡的決定并不是讓類在運作時決定,而是在編寫建立者類的時候,不需要知道實際建立的是哪一個産品。工廠方法其實就是在抽象類中定義了一個産生對象的方法,由具體的子類來實作到底産生什麼樣的對象。

工廠方法模式是簡單工廠模式的進一步抽象化和推廣,工廠方法模式裡不再隻由一個工廠類決定那一個産品類應當被執行個體化,這個決定被交給抽象工廠的子類去做。

它的組成:

1)抽象工廠角色: 這是工廠方法模式的核心,它與應用程式無關。是具體工廠角色必須實作的接口或者必須繼承的父類。在java中它由抽象類或者接口來實作。

2)具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程式調用以建立對應的具體産品的對象。

3)抽象産品角色:它是具體産品繼承的父類或者是實作的接口。在java中一般有抽象類或者接口來實作。

4)具體産品角色:具體工廠角色所建立的對象就是此角色的執行個體。在java中由具體的類來實作。

工廠方法模式使用繼承自抽象工廠角色的多個子類來代替簡單工廠模式中的“上帝類”。這樣使得結構變得靈活起來——當有新的産品産生時,隻要按照抽象産品角色、抽象工廠角色提供的合同來生成,那麼就可以被客戶使用,而不必去修改任何已有的代 碼。可以看出工廠角色的結構也是符合開閉原則的!

具體執行個體:

//抽象工廠

public abstract class CarFactory {

abstract Vehicle create();

//具體工廠

public class PlaneFactory extends CarFactory{

public Vehicle create() {

return new Plane();

publicclass BroomFactory extends CarFactory{

return new Broom();

//測試類

public class Test {

public static void main(String[] args) {

CarFactory factory = new BroomFactory();

Moveable m = factory.create();

m.run();

簡單工廠與工廠方法比較:

工廠方法模式和簡單工廠模式在定義上的不同是很明顯的。工廠方法模式的核心是一個抽象工廠類,而不像簡單工廠模式, 把核心放在一個具體的子類上。工廠方法模式可以允許很多執行個體工廠類從抽象工廠類繼承下來, 進而可以在實際上成為多個簡單工廠模式的綜合,進而推廣了簡單工廠模式。 

反過來講,簡單工廠模式是由工廠方法模式退化而來。設想如果我們非常确定一個系統隻需要一個實的工廠類, 那麼就不妨把抽象工廠類合并到實的工廠類中去。而這樣一來,我們就退化到簡單工廠模式了。

設計原則(依賴倒置原則):要依賴抽象,不要依賴具體類

高層元件和底層元件依賴于一個抽象産品。

在實際開發中,注意幾個原則,可以避免違反依賴倒置原則:

1)變量不可以持有具體類的引用。如果使用new,就會持有具體類的引用。

2)不要讓類派生自具體類。如果派生于具體類,就會依賴于具體類,一般派生于接口或抽象類。派生具體類會使子類具有一些不要的功能,而派生接口或抽象類,會将共享的部分提出,變化的部分共子類來實作。

3)不要覆寫基類中已經實作的方法。如果覆寫基類已實作的方法,那麼基類就不适合被繼承,基類實作的方法,應該由子類共享。

小思考 選擇抽象類還是接口,一般來說倘若子類都具有一些相同的功能,且功能的具有相同的行為,則使用抽象類,而把相同的功能且具有不同變化的行為交給子類來實作。倘若子類都具全部的功能且行為不同,則就用接口,并且接口可以避免java中的單繼承限制特點。

三 抽象工廠模式

它主要是用來建立一系列的産品族,抽象工廠的任務就是定義一個負責建立一組産品的接口。工廠方法其實就是潛伏在抽象工廠裡面。

舉例說明:

//抽象工廠類

public abstract class AbstractFactory {

public abstract Vehicle createVehicle();

public abstract Weapon createWeapon();

public abstract Food createFood();

//具體工廠類,其中Food,Vehicle,Weapon是抽象類,

publicclass DefaultFactory extends AbstractFactory{

@Override

public Food createFood() {

return new Apple();

public Vehicle createVehicle() {

return new Car();

public Weapon createWeapon() {

return new AK47();

AbstractFactory f = new DefaultFactory();

Vehicle v = f.createVehicle();

v.run();

Weapon w = f.createWeapon();

w.shoot();

Food a = f.createFood();

a.printName();

工廠方法和抽象工廠的比較

工廠方法使用的是類,而抽象工廠使用的是對象。他們都負責建立對象,工廠方法通過繼承來讓子類來建立具體的執行個體化類,而抽象工廠則是通過對象的組合來建立,因為抽象工廠要建立一系列的産品族。利用工廠方法來建立對象的時候需要擴充一個類,并且覆寫它的工廠方法。抽象工廠需要一個大基類,這個大基類包括了所有産品的建立的“工廠方法”。

當需要建立産品家族和想讓制造的相關産品集合起來,就是用抽象工廠。

當還不知道以後需要執行個體化哪些類的時候,可以使用工廠方法。

工廠方法,就是一個基類中包含了一個工廠方法,讓子類來決定建立哪些自己的類型産品。

抽象工廠,就是一個基類中包含了建立一系列産品的方法,讓子類來執行個體化具體的對象集合。

整體比較:

(1)簡單工廠模式是由一個具體類去建立其他類的執行個體,父類是相同的,父類是具體的。

(2)工廠方法模式是由一個抽象的父類定義的抽象方法,子類負責生成具體的對象,這樣做的目的是将類的執行個體化操作延遲到子類中完成。

(3)抽象工廠模式提供一個建立一系列相關或互相依賴對象的接口,而無須指定他們具體的類。它針對的是有多個産品的等級結構。而工廠方法模式針對的是一個産品的等級結構。

要點

1)所有的工廠都是用來封裝對象的建立的

2)工廠方法使用繼承:把對象的建立委托給子類,子類實作工廠方法來建立對象

3)抽象工廠使用對象組合:對象的建立被實作在工廠接口所暴露的方法中

4)所有的工廠模式都通過減少應用程式和具體類之間的依賴促進松耦合

5)工廠方法允許将類執行個體化延遲到子類進行

6)抽象工廠建立相關的對象家族,而不需要依賴于他們的具體類

本文轉自 zhao_xiao_long 51CTO部落格,原文連結:http://blog.51cto.com/computerdragon/1155657