設計模式學習(三):工廠模式

設計模式學習(三):工廠模式

作者:Grey

原文地址:

部落格園:設計模式學習(三):工廠模式

CSDN:設計模式學習(三):工廠模式

工廠模式

工廠模式是創建型模式,工廠模式分為:簡單工廠,工廠方法和抽象工廠三種類型。

簡單工廠

這個模式很簡單,比如我們需要製造不同類型的滑鼠,我們只需要創建一個滑鼠工廠

public class MouseFactory {
    public static Mouse createMouse(int type) {
        switch (type) {
            case 1:
                return new HpMouse();
            case 2:
                return new LenovoMouse();
            case 0:
            default:
                return new DellMouse();
        }
    }

    public static void main(String[] args) {
        Mouse mouse = MouseFactory.createMouse(1);
        mouse.sayHi();
    }
}

根據不同的 type 來創建不同的滑鼠即可。這個模式的缺點很明顯,違反了開閉原則 ,所以我們引入工廠方法

工廠方法

工廠方法中,我們可以定義對應產品的對應工廠,以上面這個滑鼠的例子為例,我們可以增加工廠的介面

public interface MouseFactory {
    Mouse createMouse();
}

不同類型的滑鼠工廠實現這個工廠即可,以 Dell 滑鼠工廠為例

public class DellMouseFactory implements MouseFactory {
    @Override
    public Mouse createMouse() {
        return new DellMouse();
    }
}

主函數在調用的時候,直接指定工廠即可製造對應的產品了:

public class FactoryMethodDemo {
    public static void main(String[] args) {
        MouseFactory mf = new HpMouseFactory();
        Mouse mouse = mf.createMouse();
        mouse.sayHi();
    }
}

工廠方法的優點是符合開閉原則,但是缺點也很明顯,就是在增加子類的時候,同時要增加一個子類的工廠,而且,只支援同一類產品的創建,不適用於同一產品族

抽象工廠

舉例,現在需要通過工廠來製造交通工具,如果是現代的工廠,製造的就是汽車,如果是古代的工廠,製造的就是馬車, 我們可以先把工廠抽象出來,

public abstract class AbstractFactory {

    protected abstract Transportation createTransportation();

    protected abstract WritingInstrument createWritingInstrument();
}

交通工具也可以抽象出來

public abstract class Transportation {
    protected abstract void go();
}

對於馬車和汽車來說,只需要繼承這個 Transportation 類,實現對應的 go 方法即可,以汽車為例

public class Car extends Transportation {
    @Override
    protected void go() {
        System.out.println("car go");
    }
}

對於現代工廠還是古代工廠,只需要繼承 AbstractFactory 這個抽象類,實現 createTransportation 方法即可,以現代工廠為例

public class ModernFactory extends AbstractFactory {

    @Override
    protected Transportation createTransportation() {
        return new Car();
    }

    @Override
    protected WritingInstrument createWritingInstrument() {
        return new Pen();
    }
}

主方法在調用的時候,只需要

public class Main {
    public static void main(String[] args) {
        AbstractFactory factory = new ModernFactory();
        factory.createTransportation().go();
    }
}

抽象工廠的UML圖如下:

image

Java SE 8 提供了 Supplier 這個函數式介面,我們可以通過這個介面很方便的實現工廠類。更多 Java SE 8 新特性見:Java SE 8 新增特性

舉例:

我們可以定義一個 MovableFactory ,裡面的 create 方法,傳入的是一個 Supplier 對象,你可以把所有 Movable 的子類實現傳給這個參數,示例如下:

public class MovableFactory {
    public static Movable create(Supplier<? extends Movable> supplier) {
        return supplier.get();
    }

    public static void main(String[] args) {
        MovableFactory.create(Car::new).go();
        MovableFactory.create(() -> new Ship()).go();
    }
}

工廠模式應用舉例

  1. JDK 中的 Calendar 類的 getInstance() 方法;

  2. LogBack 中 LoggerFactory.getLogger()方法;

  3. 在 Spring 中,所有工廠都是 BeanFactory 的子類。通過對 BeanFactory 的實現,我們可以從 Spring 的容器訪問 Bean 。根據不同的策略調用 getBean() 方法,從而獲得具體對象。

  4. Hibernate 換資料庫只需換方言和驅動就可以切換不同資料庫,也是利用了工廠模式。

UML 和 程式碼

UML 圖

程式碼

更多

設計模式學習專欄

參考資料