設計模式之工廠方法模式

0x01.定義與類型

  • 定義:定義一個建立對象的接口,但讓實現這個接口的類來決定實例化那個類,工廠方法讓類的實例化推遲到子類中進行
  • 類型:建立型
  • uml類圖

factory-method

  • 代碼
//工廠接口
public interface IFactory {
    IProduct createProduct();
}

//產品接口
public interface IProduct {
    void produce();
}

//工廠實現
public class Factory implements IFactory {
    @Override
    public IProduct createProduct() {
        return new Product();
    }
}

//產品實現
public class Product implements IProduct{
    @Override
    public void produce() {
        System.out.println("具體產品業務。");
    }
}

//應用 / 測試類
public class Test {
    public static void main(String[] args) {
        IFactory factory = new Factory();
        IProduct product = factory.createProduct();
        product.produce();
    }
}
  • 應用 / 測試類輸出結果
具體產品業務。
  • 經過工廠方法模式的類圖能夠看到,工廠方法模式有四個要素:html

    1. 工廠接口:工廠接口是工廠方法模式的核心,與調用者直接交互用來提供產品。在實際編程中,有時候也會使用一個抽象類來做爲與調用者交互的接口,其本質上是同樣的。
    2. 工廠實現:在編程中,工廠實現決定如何實例化產品,是實現擴展的途徑,須要有多少種產品,就須要有多少個具體的工廠實現。
    3. 產品接口:產品接口的主要目的是定義產品的規範,全部的產品實現都必須遵循產品接口定義的規範。產品接口是調用者最爲關心的,產品接口定義的優劣直接決定了調用者代碼的穩定性。一樣,產品接口也能夠用抽象類來代替,但要注意最好不要違反里氏替換原則。
    4. 產品實現:實現產品接口的具體類,決定了產品在客戶端中的具體行爲。

0x02.簡單工廠對比工廠方法

  • 簡單工廠只有三個要素,他沒有工廠接口,而且獲得產品的方法通常是靜態的。
  • 由於沒有工廠接口,因此在工廠實現的擴展性方面稍弱,能夠算是工廠方法模式的簡化版。
  • 簡單工廠若是發生變更是須要修改工廠方法,違反了開閉原則。

0x03.使用場景

  • 建立類模式,在任何須要生成複雜對象的地方,均可以使用工廠方法模式。有一點須要注意的地方就是複雜對象適合使用工廠模式,而簡單對象,特別是只須要經過new就能夠完成建立的對象,無需使用工廠模式。若是使用工廠模式,就須要引入一個工廠類,會增長系統的複雜度。
  • 工廠模式是一種典型的解耦模式,迪米特法則在工廠模式中表現的尤其明顯。假如調用者本身組裝產品須要增長依賴關係時,能夠考慮使用工廠模式。將會大大下降對象之間的耦合度。
  • 因爲工廠模式是依靠抽象架構的,它把實例化產品的任務交由實現類完成,擴展性比較好。也就是說,當須要系統有比較好的擴展性時,能夠考慮工廠模式,不一樣的產品用不一樣的實現工廠來組裝。
  • 總結的說前端

    1. 建立對象須要大量重複的代碼
    2. 客戶端(應用層)不依賴於產品類實例如何被建立、實現等細節
    3. 一個類經過其子類來指定建立那個對象(具備產品抽象)

0x04.優勢

  • 用戶只須要關心所須要產品對應的工廠,無需關心建立細節
  • 加入新產品符合開閉原則,提升可擴展性

0x05.缺點

  • 類的個數容易過多,增長複雜度
  • 增長了系統的抽象性和理解難度

0x06.實現樣例

  • 在線教育網站具備多種技術種類視頻
  • 視頻工廠與視頻類的定義
//視頻工廠
public abstract class VideoFactory {
    public abstract Video getVideo();
}

//視頻類
public abstract class Video {
    public abstract void produce();
}
  • Java視頻的實現
//Java視頻工廠
public class JavaVideoFactory extends VideoFactory {
    @Override
    public JavaVideo getVideo() {
        return new JavaVideo();
    }
}

//Java視頻
public class JavaVideo extends Video {
    @Override
    public void produce() {
        System.out.println("錄製Java課程視頻");
    }
}
  • Python視頻實現
//Python視頻工廠
public class PythonVideoFactory extends VideoFactory {
    @Override
    public PythonVideo getVideo() {
        return new PythonVideo();
    }
}

//Python視頻
public class PythonVideo extends Video{
    @Override
    public void produce() {
        System.out.println("錄製Python課程");
    }
}
  • 前端課程實現
//前端視頻實現
public class FEVideoFactory extends VideoFactory {
    @Override
    public FEVideo getVideo() {
        return new FEVideo();
    }
}

//前端視頻
public class FEVideo extends Video {
    @Override
    public void produce() {
        System.out.println("錄製前端視頻");
    }
}
  • 應用與測試類實現
public class Test {

    public static void main(String[] args) {
        VideoFactory videoFactory = new JavaVideoFactory();
        Video video1 = videoFactory.getVideo();
        video1.produce();

        videoFactory = new PythonVideoFactory();
        Video video2 = videoFactory.getVideo();
        video2.produce();

        videoFactory = new FEVideoFactory();
        Video video3 = videoFactory.getVideo();
        video3.produce();
    }
}
  • 輸出結果
錄製Java課程視頻
錄製Python課程
錄製前端視頻
  • 實現UML類圖

factory-method-demo

0x07.源碼中的工廠方法

  • Collection.iterator()方法java

    • 每一個集合的具體實現都有一個實現了Iterator的具體實現
    • Collection.iterator至關因而工廠方法
    • ArrayList中的iterator是其中的內部類的實現的工廠
    public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
        //省略了具體實現
    }
    • 使用私有內部類來實現具體產品,實現iterator方法,來生成具體的實現。
  • URLStreamHandlerFactory工廠
  • log4j, logback---->LoggerFactory

0x08.源碼地址

工廠方法模式https://github.com/sigmako/design-pattern/tree/master/factory-methodgit

0x09.參考

相關文章
相關標籤/搜索