設(shè)計模式詳解——工廠模式(二)

本篇文章介紹一種設(shè)計模式——工廠模式。工廠模式是用來封裝對象的創(chuàng)建,減少應(yīng)用程序和具體類之間的依賴,促進松耦合。根據(jù)工廠模式的應(yīng)用特性,一共分為三種子模式:簡單工廠模式,工廠方法模式和抽象工廠模式。本篇文章主要介紹工廠方法模式。本篇文章內(nèi)容參考工廠方法模式,【原】從頭學(xué)習(xí)設(shè)計模式(三)——工廠方法模式。

一、工廠方法模式簡介

1.定義

工廠方法模式(Factory Method Pattern)又稱為工廠模式,也叫虛擬構(gòu)造器(Virtual Constructor)模式或者多態(tài)工廠(Polymorphic Factory)模式,它屬于類創(chuàng)建型模式。

在工廠方法模式中,工廠父類負(fù)責(zé)定義創(chuàng)建產(chǎn)品對象的公共接口,而工廠子類則負(fù)責(zé)生成具體的產(chǎn)品對象,這樣做的目的是將產(chǎn)品類的實例化操作延遲到工廠子類中完成,即通過工廠子類來確定究竟應(yīng)該實例化哪一個具體產(chǎn)品類。

2.使用動機

現(xiàn)在對該系統(tǒng)(上篇文章提到)進行修改,不再設(shè)計一個按鈕工廠類來統(tǒng)一負(fù)責(zé)所有產(chǎn)品的創(chuàng)建,而是將具體按鈕的創(chuàng)建過程交給專門的工廠子類去完成。

我們先定義一個抽象的按鈕工廠類,再定義具體的工廠類來生成圓形按鈕、矩形按鈕、菱形按鈕等,它們實現(xiàn)在抽象按鈕工廠類中定義的方法。這種抽象化的結(jié)果使這種結(jié)構(gòu)可以在不修改具體工廠類的情況下引進新的產(chǎn)品,如果出現(xiàn)新的按鈕類型,只需要為這種新類型的按鈕創(chuàng)建一個具體的工廠類就可以獲得該新按鈕的實例,這一特點無疑使得工廠方法模式具有超越簡單工廠模式的優(yōu)越性,更加符合“開閉原則”。

二、工廠方法模式結(jié)構(gòu)

1.模式結(jié)構(gòu)

工廠方法模式包含如下角色:

●Product:抽象產(chǎn)品,工廠方法模式所創(chuàng)建的對象的超類,也就是所有產(chǎn)品類的共同父類或共同擁有的接口。在實際的系統(tǒng)中,這個角色也常常使用抽象類實現(xiàn)。

●ConcreteProduct:具體產(chǎn)品,這個角色實現(xiàn)了抽象產(chǎn)品(Product)所聲明的接口,工廠方法模式所創(chuàng)建的每一個對象都是某個具體產(chǎn)品的實例。

●Factory:抽象工廠,擔(dān)任這個角色的是工廠方法模式的核心,任何在模式中創(chuàng)建對象的工廠類必須實現(xiàn)這個接口。在實際的系統(tǒng)中,這個角色也常常使用抽象類實現(xiàn)。

●ConcreteFactory:具體工廠,擔(dān)任這個角色的是實現(xiàn)了抽象工廠接口的具體Java類。具體工廠角色含有與業(yè)務(wù)密切相關(guān)的邏輯,并且受到使用者的調(diào)用以創(chuàng)建具體產(chǎn)品對象。

2.時序圖

①先調(diào)用具體工廠對象中的方法createProduct()

②根據(jù)傳入產(chǎn)品類型參數(shù)(也可以無參),獲得具體的產(chǎn)品對象

③返回產(chǎn)品對象并使用

三、工廠方法模式的使用實例


上面的類圖中,在燈這個品類下,有燈泡燈管兩種產(chǎn)品,并且都實現(xiàn)了燈的通用方法:關(guān)燈和開燈。在工廠類下,有各種生產(chǎn)具體產(chǎn)品的子工廠負(fù)責(zé)生產(chǎn)相應(yīng)的兩種燈具。

如果還不是太明白,那我們來假設(shè)一個情景。小明(客戶端)想要買一個燈泡,他不認(rèn)識工廠,只能去供銷店(工廠類)買,于是和老板說“我要一個燈泡”,老板說 “沒問題!您稍等”。轉(zhuǎn)身到了后院,對生產(chǎn)燈泡的小弟(燈泡工廠子類)吆喝一聲,給我造個燈泡!不一會燈泡造好了,老板拿給小明,“嘿嘿,燈泡給您作了一個,您試試?”,小明把燈泡擰在燈口上,開關(guān)了兩下(燈的通用方法)“嘿!挺好,沒問題!”,付了錢高高興興走了。
** 抽象的產(chǎn)品接口ILight**

 public interface ILight
    {
        void TurnOn();
        void TurnOff();
    }

具體的產(chǎn)品類:BulbLight

 public class BulbLight implements ILight
    {
        public void TurnOn()
        {
            Console.WriteLine("BulbLight turns on.");
        }
        public void TurnOff()
        {
            Console.WriteLine("BulbLight turns off.");
        }
    }

**具體的產(chǎn)品類:TubeLight **

 public class TubeLight implements ILight
    {
        public void TurnOn()
        {
            Console.WriteLine("TubeLight turns on.");
        }

        public void TurnOff()
        {
            Console.WriteLine("TubeLight turns off.");
        }

    }

** 抽象的工廠類**

public interface ICreator
    {
        ILight CreateLight();
    }

具體的工廠類:BulbCreator

 public class BulbCreator implements ICreator
    {
        public ILight CreateLight()
        {
            return new BulbLight();
        }

    }

具體的工廠類:TubeCreator

 public class TubeCreator implements ICreator
    {
        public ILight CreateLight()
        {
            return new TubeLight();
        }
    }

** 客戶端調(diào)用**

static void Main(string[] args)
        {
            //先給我來個燈泡
            ICreator creator = new BulbCreator();
            ILight light = creator.CreateLight();
            light.TurnOn();
            light.TurnOff();

            //再來個燈管看看
            creator = new TubeCreator();
            light = creator.CreateLight();
            light.TurnOn();
            light.TurnOff();

        }

通過一個引用變量ICreator來創(chuàng)建產(chǎn)品對象,創(chuàng)建何種產(chǎn)品對象由指向的具體工廠類決定。通過工廠方法模式,將具體的應(yīng)用邏輯和產(chǎn)品的創(chuàng)建分離開,促進松耦合。

本例中每個具體工廠類只負(fù)責(zé)生產(chǎn)一種類型的產(chǎn)品,當(dāng)然每個具體工廠類也內(nèi)部可以維護少數(shù)幾種產(chǎn)品實例對象,類似于簡單工廠模式。

四、工廠方法模式的優(yōu)缺點

優(yōu)點

①在工廠方法模式中,工廠方法用來創(chuàng)建客戶所需要的產(chǎn)品,同時還向客戶隱藏了哪種具體產(chǎn)品類將被實例化這一細(xì)節(jié),用戶只需要關(guān)心所需產(chǎn)品對應(yīng)的工廠,無須關(guān)心創(chuàng)建細(xì)節(jié),甚至無須知道具體產(chǎn)品類的類名。

②基于工廠角色和產(chǎn)品角色的多態(tài)性設(shè)計是工廠方法模式的關(guān)鍵。它能夠使工廠可以自主確定創(chuàng)建何種產(chǎn)品對象,而如何創(chuàng)建這個對象的細(xì)節(jié)則完全封裝在具體工廠內(nèi)部。工廠方法模式之所以又被稱為多態(tài)工廠模式,是因為所有的具體工廠類都具有同一抽象父類。

③使用工廠方法模式的另一個優(yōu)點是在系統(tǒng)中加入新產(chǎn)品時,無須修改抽象工廠和抽象產(chǎn)品提供的接口,無須修改客戶端,也無須修改其他的具體工廠和具體產(chǎn)品,而只要添加一個具體工廠和具體產(chǎn)品就可以了。這樣,系統(tǒng)的可擴展性也就變得非常好,完全符合“開閉原則”,這點比簡單工廠模式更優(yōu)秀。

缺點

①在添加新產(chǎn)品時,需要編寫新的具體產(chǎn)品類,而且還要提供與之對應(yīng)的具體工廠類,系統(tǒng)中類的個數(shù)將成對增加,在一定程度上增加了系統(tǒng)的復(fù)雜度,有更多的類需要編譯和運行,會給系統(tǒng)帶來一些額外的開銷。

②由于考慮到系統(tǒng)的可擴展性,需要引入抽象層,在客戶端代碼中均使用抽象層進行定義,增加了系統(tǒng)的抽象性和理解難度,且在實現(xiàn)時可能需要用到DOM、反射等技術(shù),增加了系統(tǒng)的實現(xiàn)難度。

適用場景

在以下情況下可以使用工廠方法模式:

①一個類不知道它所需要的對象的類:在工廠方法模式中,客戶端不需要知道具體產(chǎn)品類的類名,只需要知道所對應(yīng)的工廠即可,具體的產(chǎn)品對象由具體工廠類創(chuàng)建;客戶端需要知道創(chuàng)建具體產(chǎn)品的工廠類。

②一個類通過其子類來指定創(chuàng)建哪個對象:在工廠方法模式中,對于抽象工廠類只需要提供一個創(chuàng)建產(chǎn)品的接口,而由其子類來確定具體要創(chuàng)建的對象,利用面向?qū)ο蟮亩鄳B(tài)性和里氏代換原則,在程序運行時,子類對象將覆蓋父類對象,從而使得系統(tǒng)更容易擴展。

③將創(chuàng)建對象的任務(wù)委托給多個工廠子類中的某一個,客戶端在使用時可以無須關(guān)心是哪一個工廠子類創(chuàng)建產(chǎn)品子類,需要時再動態(tài)指定,可將具體工廠類的類名存儲在配置文件或數(shù)據(jù)庫中。

五、工廠方法模式在Java中應(yīng)用

JDBC中的工廠方法:

Connection conn=DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=DB;user=sa;password=");
Statement statement=conn.createStatement();
ResultSet rs=statement.executeQuery("select * from UserInfo");
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 設(shè)計模式匯總 一、基礎(chǔ)知識 1. 設(shè)計模式概述 定義:設(shè)計模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 4,093評論 1 15
  • 1 場景問題# 1.1 導(dǎo)出數(shù)據(jù)的應(yīng)用框架## 考慮這樣一個實際應(yīng)用:實現(xiàn)一個導(dǎo)出數(shù)據(jù)的應(yīng)用框架,來讓客戶選擇數(shù)據(jù)...
    七寸知架構(gòu)閱讀 7,016評論 6 75
  • 設(shè)計模式基本原則 開放-封閉原則(OCP),是說軟件實體(類、模塊、函數(shù)等等)應(yīng)該可以拓展,但是不可修改。開-閉原...
    西山薄涼閱讀 4,081評論 3 14
  • 簡單工廠模式雖然簡單,但存在一個很嚴(yán)重的問題。當(dāng)系統(tǒng)中需要引入新產(chǎn)品時,由于靜態(tài)工廠方法通過所傳入?yún)?shù)的不同來創(chuàng)建...
    justCode_閱讀 1,308評論 1 9
  • 外出幾天,公號、簡書都停更了。 本周周記可寫東西也不多。 一、每日精進 雖是出門在外,但每天該做的一樣也沒落下。 ...
    櫻桃莊園閱讀 261評論 0 0

友情鏈接更多精彩內(nèi)容