一塊兒學設計模式 - 工廠模式

工廠模式是JAVA中最經常使用的設計模式之一,使用工廠模式後,建立對象的時候不在將建立邏輯暴露給客戶端,而是經過實現接口的方式建立對象,這種設計模式也是對象實例化的最佳方式。html

<!-- more -->java

概述

工廠模式的三種形態git

  • 簡單工廠(Simple Factory)
  • 工廠方法(Factory Method)
  • 抽象工廠(Abstract Factory)

簡單工廠

簡單工廠模式屬於工廠模式的小弟,未被收納進GOF 23中,可是也被頻繁使用編程

簡單工廠模式

1.建立一個Animal接口設計模式

interface Shape {
    void draw();
}

2.建立DogPig實現Animal接口微信

class Circle implements Shape {
    public Circle() {
        System.out.println("建立圓形模型");
    }

    @Override
    public void draw() {
        System.out.println("畫了一個圓形");
    }
}

class Square implements Shape {
    public Square() {
        System.out.println("建立了方形模型");
    }

    @Override
    public void draw() {
        System.out.println("畫了一個方形");
    }
}

3.建立工廠類SimpleFactory,定義一個基於參數信息實例化具體對象的方法ide

public class SimpleFactory {

    private final static String CIRCLE = "CIRCLE";
    private final static String SQUARE = "SQUARE";

    public static Shape getFactory(String type) {
        switch (type) {
            case CIRCLE:
                return new Circle();
            case SQUARE:
                return new Square();
            default:
                throw new NullPointerException("未描繪任何圖形");
        }
    }

    public static void main(String[] args) {
        Shape circle = SimpleFactory.getFactory(CIRCLE);
        circle.draw();

        Shape square = SimpleFactory.getFactory(SQUARE);
        square.draw();
    }
}

4.日誌測試

建立圓形模型
畫了一個圓形
建立了方形模型
畫了一個方形

分析: 從上述代碼中能夠發現,簡單工廠擁有必定判斷能力,構建結果取決於入參,使用起來也十分的方便,也正由於使用太過方便而致使高耦合的狀況,全部對象實例化都須要依賴它,一旦出問題,影響的會是整個系統spa

使用場景: 建立簡單,無複雜業務邏輯的對象操作系統

工廠方法

前面說到過簡單工廠模式存在耦合,且違反了開閉原則,那麼這一問題在工廠方法模式中能夠很容易的解決掉,它能夠作到添加新的產品而不破壞已有代碼

工廠方法模式

工廠方法模式:定義一個建立對象的接口,由它的實現類來決定具體實現,其模式又被稱爲工廠模式(Factory Pattern)

1.新增ImageReaderFactory抽象工廠接口,用來構建具體的對象

interface ImageReader {
    void read();
}
interface ImageReaderFactory {
    ImageReader create();
}

2.相比單一實例化的簡單工廠模式而言,方法工廠模式更加的靈活,針對不一樣的產品(圖片讀取器)提供不一樣的工廠。

class JpgReader implements ImageReader {
    public JpgReader() {
        System.out.println("建立Jpg讀取器");
    }

    @Override
    public void read() {
        System.out.println("讀取Jpg文件");
    }
}

class PngReader implements ImageReader {
    public PngReader() {
        System.out.println("建立Png讀取器");
    }

    @Override
    public void read() {
        System.out.println("讀取Png文件");
    }
}
class JpgFactory implements ImageReaderFactory {
    @Override
    public ImageReader create() {
        System.out.println("實例化Jpg文件工廠");
        return new JpgReader();
    }
}

class PngFactory implements ImageReaderFactory {
    @Override
    public ImageReader create() {
        System.out.println("實例化Png文件工廠");
        return new PngReader();
    }
}

3.建立測試類,固然實際使用過程當中,實現工廠方法除了能夠實例化具體對象,還能夠初始化某些資源配置,好比鏈接池、建立文件等

public class MethodFactory {
    public static void main(String[] args) {
        ImageReaderFactory png = new PngFactory();
        ImageReader pngReader = png.create();
        pngReader.read();

        ImageReaderFactory jpg = new JpgFactory();
        ImageReader jpgReader = jpg.create();
        jpgReader.read();
    }
}

4.日誌

實例化Png文件工廠
建立Png讀取器
讀取Png文件
實例化Jpg文件工廠
建立Jpg讀取器
讀取Jpg文件

優勢:

  • 屏蔽了客戶端實例化對象的細節,用戶只須要關心本身使用的工廠便可。
  • 加入新的產品(圖片讀取器),無需更改現有代碼,提升系統擴展性,符合開閉原則
  • 具有多態性,又被稱爲多態工廠模式

缺點: 每次須要編寫新的對象和對象工廠類,隨業務發展,必定程度上增長了系統複雜度

抽象工廠

  • 抽象工廠模式是爲建立一組對象提供提供的解決方案,與工廠方法模式相比,抽象工廠模式中的具體工廠不僅是建立某一種產品,而是負責一組(產品族)。
  • 抽象工廠模式(Abstract Factory Pattern):提供了建立一系列相互依賴對象的接口,無需指定具體類
  • 抽象工廠模式是圍繞着一個超級工廠工做,創造其它的工廠類,也被稱爲工廠的工廠,這種類型的設計模式是創造性的模式,由於這種模式提供了建立對象的最佳方法之一。

起源

抽象工廠模式的起源或者最先的應用,是用於建立分屬於不一樣操做系統的視窗構建。好比:命令按鍵(Button)與文字框(Text)都是視窗構建,在UNIX操做系統的視窗環境和Windows操做系統的視窗環境中,這兩個構建有不一樣的本地實現,它們的細節有所不一樣。

在每個操做系統中,都有一個視窗構建組成的構建家族。在這裏就是Button和Text組成的產品族。而每個視窗構件都構成本身的等級結構,由一個抽象角色給出抽象的功能描述,而由具體子類給出不一樣操做系統下的具體實現。

444

能夠發如今上面的產品類圖中,有兩個產品的等級結構,分別是Button等級結構和Text等級結構。同時有兩個產品族,也就是UNIX產品族和Windows產品族。UNIX產品族由UNIX Button和UNIX Text產品構成;而Windows產品族由Windows Button和Windows Text產品構成。

555

系統對產品對象的建立需求由一個工程的等級結構知足,其中有兩個具體工程角色,即UnixFactory和WindowsFactory。UnixFactory對象負責建立Unix產品族中的產品,而WindowsFactory對象負責建立Windows產品族中的產品。這就是抽象工廠模式的應用,抽象工廠模式的解決方案以下圖:

666

顯然,一個系統只可以在某一個操做系統的視窗環境下運行,而不能同時在不一樣的操做系統上運行。因此,系統實際上只能消費屬於同一個產品族的產品。

在現代的應用中,抽象工廠模式的使用範圍已經大大擴大了,再也不要求系統只能消費某一個產品族了。所以,能夠沒必要理會前面所提到的原始用意。

摘抄自《JAVA與模式》之抽象工廠模式:http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html

需求: 開發一款《王者榮耀》,支持多操做系統和多控制方式操做控制界面控制,並提供相應的工廠類來封裝這些類的初始化過程

抽象工廠模式

1.建立不一樣的操做系統接口

interface Linux {
    void controller();
}

interface Windows {
    void controller();
}

2.基於不一樣操做系統實現控制邏輯

class LinuxController implements Linux {
    @Override
    public void controller() {
        System.out.println("Linux 控制 《王者榮耀》");
    }
}

class WindowsController implements Windows {
    @Override
    public void controller() {
        System.out.println("Windows 控制 《王者榮耀》");
    }
}

3.建立一個工廠類,基於接口分別實現操做控制界面控制兩種方式的工廠

interface AbstractFactory {
    Linux installLinux();

    Windows installWindows();
}

class OperationFactory implements AbstractFactory {

    @Override
    public Linux installLinux() {
        System.out.println("安裝Linux操做控制系統");
        return new LinuxController();
    }

    @Override
    public Windows installWindows() {
        System.out.println("安裝Windows操做控制系統");
        return new WindowsController();
    }
}

class InterfaceFactory implements AbstractFactory {
    @Override
    public Linux installLinux() {
        System.out.println("安裝Linux界面控制系統");
        return new LinuxController();
    }

    @Override
    public Windows installWindows() {
        System.out.println("安裝Windows界面控制系統");
        return new WindowsController();
    }
}

4.建立《王者榮耀》進行測試

public class KingGlory {

    public static void main(String[] args) {

        AbstractFactory operationFactory = new OperationFactory();
        operationFactory.installLinux().controller();
        operationFactory.installWindows().controller();
        System.out.println("========================================================");
        AbstractFactory interfaceFactory = new InterfaceFactory();
        interfaceFactory.installLinux().controller();
        interfaceFactory.installWindows().controller();

    }
}

5.日誌

安裝Linux操做控制系統
Linux 控制 《王者榮耀》
安裝Windows操做控制系統
Windows 控制 《王者榮耀》
========================================================
安裝Linux界面控制系統
Linux 控制 《王者榮耀》
安裝Windows界面控制系統
Windows 控制 《王者榮耀》

分析

使用抽象工廠模式來定義的一系列對象一般是相關或相互依賴的,這些產品對象就構成了一個產品族,也就是抽象工廠定義了一個產品族。這就帶來很是大的靈活性,切換產品族的時候,只要提供不一樣的抽象工廠實現就能夠了,也就是說如今是以一個產品族做爲一個總體被切換,從上文中能夠發現,若是咱們須要切換控制方式,只須要變動下對應的工廠類便可

優勢:

  • 分離接口和實現:客戶端使用抽象工廠來建立須要的對象,而客戶端根本就不知道具體的實現是誰,客戶端只是面向產品的接口編程而已。也就是說,客戶端從具體的產品實現中解耦。
  • 切換產品族變得容易:對於增長新的產品族,抽象工廠模式很好地支持了開閉原則,只須要增長具體產品並對應增長一個新的具體工廠,對已有代碼無須作任何修改(如:新增一種手柄操做支持)。

缺點:

  • 不易擴展新產品:若是須要給整個產品族添加一個新的產品,那麼就須要修改抽象工廠,這樣就會致使修改全部的工廠實現類(如:新增一種操做系統的支持,那麼Factory代碼須要所有修改)。

使用場景:

  • 一個系統不該當依賴於產品類實例如何被建立、組合和表達的細節,這對於全部形態的工廠模式都是重要的。
  • 這個系統的產品有多於一個的產品族,而系統只消費其中某一族的產品。
  • 同屬於同一個產品族的產品是在一塊兒使用的,這一約束必須在系統的設計中體現出來。
  • 系統提供一個產品類的庫,全部的產品以一樣的接口出現,從而使客戶端不依賴於實現。

- 說點什麼

全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter1/battcn-factory

  • 我的QQ:1837307557
  • battcn開源羣(適合新手):391619659

微信公衆號:battcn(歡迎調戲)

相關文章
相關標籤/搜索