Java設(shè)計模式----工廠模式

工廠模式實現(xiàn)了創(chuàng)建者和調(diào)用者的分離。

面向?qū)ο笤O(shè)計的基本原則:

  • OCP(開閉原則,Open-Closed Principle):一個軟件的實體應(yīng)當(dāng)對擴(kuò)展開發(fā),對修改關(guān)閉;
  • DIP(依賴倒轉(zhuǎn)原則,Dependence Inversion Principle):要針對接口編程,不要針對實現(xiàn)編程;
  • LoD(迪米特法則,Law of Demeter):只與你直接的朋友通信,而避免和陌生人通信
    核心本質(zhì):
  • 實例化對象,用工廠方法代替new操作;
  • 將選擇實現(xiàn)類、創(chuàng)建對象統(tǒng)一管理和控制;從而將調(diào)用者跟我們的實現(xiàn)解耦;

簡單工廠模式

用來生產(chǎn)同一等級結(jié)構(gòu)中的任意產(chǎn)品;(對于新增的產(chǎn)品,需要修改已有代碼)

package factory.simplefactory;

public interface Car {
    void run();
}
package factory.simplefactory;

public class Audi implements Car {
    public void run() {
        System.out.println("奧迪Run");
    }
}
package factory.simplefactory;

public class Byd implements Car {
    public void run() {
        System.out.println("比亞迪Run");
    }
}
package factory.simplefactory;

public class CarFactory {
    public static Car createCar(String type){
        if ("奧迪".equals(type)){
            return new Audi();
        }else if ("比亞迪".equals(type)){
            return new Byd();
        }else {
            return null;
        }
    }
}

public class CarFactory02 {
    public static Car createAudi(){
        return new Audi();
    }
    public static Car createByd(){
        return new Byd();
    }
}
package factory.simplefactory;

public class Client02 {
    public static void main(String[] args) {
        Car c1 = CarFactory.createCar("奧迪");
        Car c2 = CarFactory.createCar("比亞迪");

        c1.run();
        c2.run();
    }
}

要點

  • 簡單工廠模式也叫靜態(tài)工廠模式,就是工廠類一般是使用靜態(tài)方法,通過接收的參數(shù)的不同來返回不同的對象實例;
  • 對于增加新產(chǎn)品無能為力!不修改代碼的話,是無法擴(kuò)展的;

工廠方法模式

用來生產(chǎn)同一等級結(jié)構(gòu)中的固定產(chǎn)品;(支持增加任意產(chǎn)品)

要點

  • 為了避免簡單工廠模式的缺點,不完全滿足OCP;
  • 工廠方法模式和簡單工廠模式最大的不同在于,簡單工廠模式只有一個(對于一個項目或者一個獨(dú)立模塊而言)工廠類,而工廠方法模式有一組實現(xiàn)了相同接口的工廠類;
package factory.factorymethod;

public interface CarFactory {
    Car createCar();
}
package factory.factorymethod;

public class AudiFactory implements CarFactory{
    public Car createCar() {
        return new Audi();
    }
}
package factory.factorymethod;

public class BydFactory implements CarFactory {
    public Car createCar() {
        return new Byd();
    }
}
package factory.factorymethod;

public class Client {
    public static void main(String[] args) {
        Car c1 = new AudiFactory().createCar();
        Car c2 = new BydFactory().createCar();

        c1.run();
        c2.run();
    }
}

簡單工廠模式和工廠方法模式PK

  1. 結(jié)構(gòu)復(fù)雜度
    從這個角度比較,顯然簡單工廠模式要占優(yōu);簡單工廠模式只需要一個工廠類,而工廠方法模式的工廠類隨著產(chǎn)品類個數(shù)增加而增加,這無疑會使類的個數(shù)越來越多,從而增加結(jié)構(gòu)的復(fù)雜程度;
  2. 代碼復(fù)雜度
    代碼復(fù)雜度和結(jié)構(gòu)復(fù)雜度是一對矛盾,既然簡單工廠模式在結(jié)構(gòu)方面相對簡潔,那么它在代碼方面肯定是比工廠方法模式復(fù)雜的了,簡單工廠類隨著產(chǎn)品的增加需要增加很多方法(或代碼),而工廠方法模式每個具體工廠類值完成單一任務(wù),代碼簡潔;
  3. 客戶端編程難度
    工廠方法模式雖然在工廠類結(jié)構(gòu)中引入了接口從而滿足了OCP,但是在客戶端編碼中需要對工廠類進(jìn)行實例化;而簡單工廠模式的工廠類是一個靜態(tài)類,在客戶端無需實例化,這無疑是吸引人的優(yōu)點;
  4. 管理上的難度
    這是個關(guān)鍵問題
    我們先談擴(kuò)展,眾所周知,工廠方法模式完全滿足OCP,即它有非常良好額擴(kuò)展性;那是否就說明了簡單工廠模式就沒有擴(kuò)展性呢?答案是否定的;簡單工廠模式同樣具有良好的擴(kuò)展性---擴(kuò)展的時候僅需要修改少量的代碼(修改工廠類的代碼)就可以滿足擴(kuò)展的要求了;盡管這沒有完全滿足OCP,但我們不需要太拘泥于設(shè)計理論,要知道,sun提供的java官方工具包中也有相當(dāng)多沒有滿足OCP的例子
    然后我們從維護(hù)性的角度分析下,假如某個具體產(chǎn)品類需要進(jìn)行一定的修改,很可能需要修改對應(yīng)的工廠類;當(dāng)同時需要修改多個產(chǎn)品類的時候,對工廠類的修改會變得相當(dāng)麻煩(對號入座已經(jīng)是一個問題了);反而簡單工廠沒有這些麻煩,當(dāng)多個產(chǎn)品需要修改時,簡單工廠模式仍然僅僅需要修改唯一的工廠類;

抽象工廠模式{#jump}

  • 用來生產(chǎn)不同產(chǎn)品族的全部產(chǎn)品;(對于增加新的產(chǎn)品,無能為力;支持增加產(chǎn)品族)
  • 抽象工廠模式是工廠方法模式的升級版本,在有多個業(yè)務(wù)品種、業(yè)務(wù)分類時,通過抽象工廠模式產(chǎn)生需要的對象時一種非常好的解決方式;
package factory.abstractfactory;

public interface Engine {
    void run();
    void start();
}

class LuxuryEngine implements Engine{
    public void run() {
        System.out.println("馬力大!");
    }

    public void start() {
        System.out.println("啟動快,加速快!");
    }
}

class LowEngine implements Engine{
    public void run() {
        System.out.println("馬力小!");
    }

    public void start() {
        System.out.println("啟動慢,加速慢!");
    }
}
package factory.abstractfactory;

public interface Seat {
    void massage();
}

class LuxurySeat implements Seat{
    public void massage() {
        System.out.println("可以按摩");
    }
}

class LowSeat implements Seat{
    public void massage() {
        System.out.println("不可以按摩");
    }
}
package factory.abstractfactory;

public interface Tyre {
    void revolve();
}

class LuxuryTyre implements Tyre{
    public void revolve() {
        System.out.println("耐磨");
    }
}

class LowTyre implements Tyre{
    public void revolve() {
        System.out.println("不耐磨");
    }
}
package factory.abstractfactory;

public interface CarFactory {
    Engine createEngine();
    Seat createSeat();
    Tyre createTyre();
}
package factory.abstractfactory;

public class LuxuryCarFactory implements CarFactory{
    public Engine createEngine() {
        return new LuxuryEngine();
    }

    public Seat createSeat() {
        return new LuxurySeat();
    }

    public Tyre createTyre() {
        return new LuxuryTyre();
    }
}
package factory.abstractfactory;

public class LowCarFactory implements CarFactory{
    public Engine createEngine() {
        return new LowEngine();
    }

    public Seat createSeat() {
        return new LowSeat();
    }

    public Tyre createTyre() {
        return new LowTyre();
    }
}
package factory.abstractfactory;

public class Client {
    public static void main(String[] args) {
        CarFactory factory = new LuxuryCarFactory();
        Engine e = factory.createEngine();
        e.run();
        e.start();
    }
}

工廠模式要點

  • 簡單工廠模式(靜態(tài)工廠模式)
    雖然某種程度不符合設(shè)計原則,但實際使用最多
  • 工廠方法模式
    不修改已有類的前提下,通過增加新的工廠類實現(xiàn)擴(kuò)展
  • 抽象工廠模式
    不可以增加產(chǎn)品,可以增加產(chǎn)品族

應(yīng)用場景

  • JDK中Calendar的getInstance方法
  • JDBC中的Connection對象的獲取
  • Hibernate中SessionFactory創(chuàng)建Session
  • Spring中IOC容器創(chuàng)建管理bean對象
  • XML解析時的DocumentBuilderFactory創(chuàng)建解析器對象
  • 反射中Class對象的newInstance()
最后編輯于
?著作權(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)容

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