程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 設計模式之工廠模式VS抽象工廠,設計模式vs

設計模式之工廠模式VS抽象工廠,設計模式vs

編輯:JAVA綜合教程

設計模式之工廠模式VS抽象工廠,設計模式vs


一、工廠模式主要是為創建對象提供過渡接口,以便將創建對象的具體過程屏蔽隔離起來,達到提高靈活性的目的。

工廠模式在《Java與模式》中分為三類:
1)簡單工廠模式(Simple Factory):不利於產生系列產品;

2)工廠方法模式(Factory Method):又稱為多形性工廠;

3)抽象工廠模式(Abstract Factory):又稱為工具箱,產生產品族,但不利於產生新的產品;
             這三種模式從上到下逐步抽象,並且更具一般性。
             GOF在《設計模式》一書中將工廠模式分為兩類:工廠方法模式(Factory Method)與抽象工廠模式(Abstract Factory)。將簡單工廠模式(Simple Factory)看為工廠方法模式的一種特例,兩者歸為一類。

二、簡單工廠模式

簡單工廠模式又稱靜態工廠方法模式。重命名上就可以看出這個模式一定很簡單。它存在的目的很簡單:定義一個用於創建對象的接口。


在簡單工廠模式中,一個工廠類處於對產品類實例化調用的中心位置上,它決定那一個產品類應當被實例化, 如同一個交通警察站在來往的車輛流中,決定放行那一個方向的車輛向那一個方向流動一樣。         先來看看它的組成:

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

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

         3) 具體產品角色:工廠類所創建的對象就是此角色的實例。在java中由一個具體類實現。 三、工廠方法模式
工廠方法模式是簡單工廠模式的進一步抽象化和推廣,工廠方法模式裡不再只由一個工廠類決定那一個產品類應當被實例化,這個決定被交給抽象工廠的子類去做。
  來看下它的組成:

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

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

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

       4)具體產品角色:具體工廠角色所創建的對象就是此角色的實例。在java中由具體的類來實現。
       工廠方法模式使用繼承自抽象工廠角色的多個子類來代替簡單工廠模式中的“上帝類”。正如上面所說,這樣便分擔了對象承受的壓力;而且這樣使得結構變得靈活 起來——當有新的產品(即暴發戶的汽車)產生時,只要按照抽象產品角色、抽象工廠角色提供的合同來生成,那麼就可以被客戶使用,而不必去修改任何已有的代 碼。可以看出工廠角色的結構也是符合開閉原則的! 代碼:
package cn.happy.b;
//抽象產品角色
public class LeiFeng {
    public void sweep(){
        System.out.println("掃地");
    }
    public void wash(){
        System.out.println("洗衣服");
    }
}
package cn.happy.b;
//具體產品角色
public class Student extends LeiFeng{

}
package cn.happy.b;
//具體產品角色
public class Volunter extends LeiFeng{

}
package cn.happy.b;
//抽象工廠
public interface IFactory {
    public LeiFeng getLeiFeng();
}
package cn.happy.b;
//具體工廠
public class StudentFactory implements IFactory{

    @Override
    public LeiFeng getLeiFeng() {        
        return new Student();
    }

}
package cn.happy.b;
//具體工廠
public class VolunterFactory implements IFactory{

    @Override
    public LeiFeng getLeiFeng() {
        
        return new Volunter();
    }

}
package cn.happy.b;

//測試類
public class Test {

    public static void main(String[] args) {
        IFactory factory=new StudentFactory();
        //IFactory factory=new VolunterFactory();
        LeiFeng stu=factory.getLeiFeng();
        stu.wash();
        stu.sweep();

    }

}

工廠方法定義:

定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到了子類

在簡單工廠中,工廠類與分支耦合,所以我們就對工廠類下手,把工廠類抽象出一個接口,

這個接口只有一個方法,就是創建抽象產品的工廠方法,然後所有要生產具體的工廠,都實現這個接口,這樣簡單工廠的工廠類就變成了一個工廠抽象接口和多個具體生產對象的工廠,要增加功能,就不需要更改原來的工廠類,之需要增加此功能的類和相應的工廠類就可以了

四、簡單工廠和工廠方法模式的比較

工廠方法模式和簡單工廠模式在定義上的不同是很明顯的。工廠方法模式的核心是一個抽象工廠類,而不像簡單工廠模式, 把核心放在一個實類上。工廠方法模式可以允許很多實的工廠類從抽象工廠類繼承下來, 從而可以在實際上成為多個簡單工廠模式的綜合,從而推廣了簡單工廠模式。 
反過來講,簡單工廠模式是由工廠方法模式退化而來。設想如果我們非常確定一個系統只需要一個實的工廠類, 那麼就不妨把抽象工廠類合並到實的工廠類中去。而這樣一來,我們就退化到簡單工廠模式了。 五、抽象工廠模式

定義:

提供一個創建一系列相關或相互依賴對象的接口,而無須指定他們具體的類

抽象工廠模式:

 

多個抽象產品類,每個抽象產品類可以派生出多個具體產品類。   
一個抽象工廠類,可以派生出多個具體工廠類。   
每個具體工廠類可以創建多個具體產品類的實例。

 

抽象工廠模式與工廠方法模式的區別

 

        抽象工廠模式是工廠方法模式的升級版本,他用來創建一組相關或者相互依賴的對象。他與工廠方法模式的區別就在於,工廠方法模式針對的是一個產品等級結構;而抽象工廠模式則是針對的多個產品等級結構。在編程中,通常一個產品結構,表現為一個接口或者抽象類,也就是說,工廠方法模式提供的所有產品都是衍生自同一個接口或抽象類,而抽象工廠模式所提供的產品則是衍生自不同的接口或抽象類。

 

        在抽象工廠模式中,有一個產品族的概念:所謂的產品族,是指位於不同產品等級結構中功能相關聯的產品組成的家族。抽象工廠模式所提供的一系列產品就組成一個產品族;而工廠方法提供的一系列產品稱為一個等級結構。我們依然拿生產汽車的例子來說明他們之間的區別。

在上面的類圖中,User和Student是兩個抽象產品,之所以為抽象,是因為他們都有可能有兩種不同的實現,而SqlUser、AccessUser和SqlStudent、AccessStudent

就是對這兩個抽象產品的具體分類

IFactory是一個抽象工廠接口,他裡面應該包含所有產品創建的抽象方法,SqlFactory和AccessFatory就是具體工廠;

 

代碼:

package cn.happy.c;

public class User {
    private int id;
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
package cn.happy.c;

public class Student {
    private int id;
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
package cn.happy.c;
/**
 * IUser接口,用於客戶端訪問,解除與具體數據庫訪問的耦合
 * @author 川哥哥
 *
 */
public interface IUser {
    public void insert(User user);
    public User getUser(int id);
}
package cn.happy.c;

public interface IStudent {
    public void insert(Student stu);
    public Student getUser(int id);
}
package cn.happy.c;

public class SqlUser implements IUser{

    @Override
    public void insert(User user) {
        System.out.println("sql中給user表添加一條記錄");
    }

    @Override
    public User getUser(int id) {
        System.out.println("在sql中根據id得到一條記錄");
        return null;
    }

}
package cn.happy.c;

public class AccessUser implements IUser{

    @Override
    public void insert(User user) {
        System.out.println("Access中給user表添加一條記錄");
        
    }

    @Override
    public User getUser(int id) {
        System.out.println("在Access中根據id得到一條記錄");
        return null;
    }

}
package cn.happy.c;

public class SqlStudent implements IStudent{

    @Override
    public void insert(Student stu) {
        System.out.println("在sql中給student表添加一條記錄");
        
    }

    @Override
    public Student getUser(int id) {
        System.out.println("在sql中,根據Id得到一條記錄");
        return null;
    }

}
package cn.happy.c;

public class AccessStudent implements IStudent{
    @Override
    public void insert(Student stu) {
        System.out.println("在Access中給student表添加一條記錄");
        
    }

    @Override
    public Student getUser(int id) {
        System.out.println("在Access中,根據Id得到一條記錄");
        return null;
    }
}
package cn.happy.c;
/**
 * 定義一個接口,創建訪問user表對象的抽象工廠類
 * @author 川哥哥
 *
 */
public interface IFactory {
    public IUser creIUser();
    public IStudent greateStudent();
}
package cn.happy.c;
/**
 * 實現Ifactory接口,實例化SqlUser
 * @author 川哥哥
 *
 */
public class 
SqlFactory implements IFactory{

    @Override
    public IUser creIUser() {
        
        return new SqlUser();
    }

    @Override
    public IStudent greateStudent() {
        // TODO Auto-generated method stub
        return new SqlStudent();
    }
    

}
package cn.happy.c;

public class AccessFactory implements IFactory{

    @Override
    public IUser creIUser() {
        
        return new AccessUser();
    }

    @Override
    public IStudent greateStudent() {
        // TODO Auto-generated method stub
        return new AccessStudent();
    }

}

測試類

package cn.happy.c;

public class Test {

    public static void main(String[] args) {
        
        User user=new User();
        Student stu=new Student();
        IFactory factory=new SqlFactory();
        //IFactory factory=new AccessFactory();
        IUser iUser=factory.creIUser();
        IStudent is=factory.greateStudent();
        iUser.insert(user);
        iUser.getUser(1);
        is.insert(stu);
        is.getUser(1);
 }
}

運行結果:

sql中給user表添加一條記錄
在sql中根據id得到一條記錄
在sql中給student表添加一條記錄
在sql中,根據Id得到一條記錄

抽象工廠模式的優點

        抽象工廠模式除了具有工廠方法模式的優點外,最主要的優點就是可以在類的內部對產品族進行約束。所謂的產品族,一般或多或少的都存在一定的關聯,抽象工廠模式就可以在類內部對產品族的關聯關系進行定義和描述,而不必專門引入一個新的類來進行管理。

 

抽象工廠模式的缺點

       產品族的擴展將是一件十分費力的事情,假如產品族中需要增加一個新的產品,則幾乎所有的工廠類都需要進行修改。所以使用抽象工廠模式時,對產品等級結構的劃分是非常重要的。

 

適用場景

       當需要創建的對象是一系列相互關聯或相互依賴的產品族時,便可以使用抽象工廠模式。說的更明白一點,就是一個繼承體系中,如果存在著多個等級結構(即存在著多個抽象類),並且分屬各個等級結構中的實現類之間存在著一定的關聯或者約束,就可以使用抽象工廠模式。假如各個等級結構中的實現類之間不存在關聯或約束,則使用多個獨立的工廠來對產品進行創建,則更合適一點。

 

總結

       無論是簡單工廠模式,工廠方法模式,還是抽象工廠模式,他們都屬於工廠模式,在形式和特點上也是極為相似的,他們的最終目的都是為了解耦。在使用時,我們不必去在意這個模式到底工廠方法模式還是抽象工廠模式,因為他們之間的演變常常是令人琢磨不透的。經常你會發現,明明使用的工廠方法模式,當新需求來臨,稍加修改,加入了一個新方法後,由於類中的產品構成了不同等級結構中的產品族,它就變成抽象工廠模式了;而對於抽象工廠模式,當減少一個方法使的提供的產品不再構成產品族之後,它就演變成了工廠方法模式。

       所以,在使用工廠模式時,只需要關心降低耦合度的目的是否達到了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved