設計模式-----簡單工廠模式

簡單工廠模式

概念

簡單工廠模式屬於建立型模式,又叫作靜態工廠方法(Static Factory Method)。簡單工廠模式是由一個工廠對象決定建立哪種產品類實例。在簡單工廠模式中,能夠根據參數的不一樣返回不一樣類的實例。簡單工廠模式專門定義一個類來負責建立其餘類的實例,被建立的實例一般都具備共同的父類。簡單工廠模式是工廠模式家族中最簡單實用的模式,能夠理解爲不一樣工廠模式的一個特殊實現java

值得注意的是,簡單工廠模式並不屬於GOF設計模式之一。可是他說抽象工廠模式,工廠方法模式的基礎,而且有普遍得應用設計模式

模式結構

組成

從上圖中能夠看出,簡單工廠模式由三部分組成:具體工廠、抽象產品和具體產品app

  • 工廠類(Creator):這是本模式的核心,含有必定的商業邏輯和判斷邏輯。在java中,它每每由一個具體的類實現
  • 抽象產品(AbstractProduct):它通常是具體產品繼承的父類或者實現的接口。在Java中,由接口或者抽象類實現
  • 具體產品(ConcreteProduct):工廠類所建立的對象就是此角色的實例。在java中 由一個具體的類實現

實例分析

需求:有蘋果類和香蕉類,他們都有get方法,經過主函數對它們進行實例化,並調用get方法

方式一:最基本的實例化

Apple.java:
public class Apple {
    /**
     * 採集蘋果
     */
    public void get(){
        System.out.println("採集蘋果");
        }
}
Banana.java:
public class Banana {
    /**
     * 採集香蕉
     */
    public void get(){
        System.out.println("採集香蕉");
    }
}
MainClass.java:
public class Mainclass{
    public static void main(String[] args){
        /**
         * 最基本的實例化方式
         */
        //實例化一個Apple
        Apple apple = new Apple();
        //實例化一個Banana
        Banana banana = new Banana();
        
        apple.get();
        banana.get();
    }
}

方式二:都有get方法,咱們能夠用多態的方式抽象出一個接口類實現

Fruit.java:
public interface Fruit {
    public void get();
}
Apple.java:
public class Apple implements Fruit{
    @Override
    //重寫get方法
    public void get(){
        System.out.println("採集蘋果");
    }
}
Banana.java:
public class Banana implements Fruit{
    @Override
    //重寫get方法
    public void get(){
        System.out.println("採集香蕉");
    }
}
MainClass.java:
public class Mainclass{
    public static void main(String[] args){
        /**
         * 多態的實例化方式
         */
        Fruit apple = FruitFactory.getApple();
        Fruit banana = FruitFactory.getBanana();

        apple.get();
        banana.get();
    }
}

方式三:新增一個工廠類實現對象的建立和主要邏輯

FruitFactory:
public class FruitFactory {
    /**
     * 得到Apple類的實例
     */
    public static Fruit getApple(){
        return new Apple();
    }

    /**
     * 得到Banana類的實例
     */
    public static Fruit getBanana(){
        return new Banana();
    }
}
Fruit.java:不變
public interface Fruit {
    public void get();
}
Apple.java:不變
public class Apple implements Fruit{
    @Override
    //重寫get方法    
    public void get(){
        System.out.println("採集蘋果");
    }
}
Banana.java:不變
public class Banana implements Fruit{
    @Override
    //重寫get方法
    public void get(){
        System.out.println("採集香蕉");
    }
}
MainClass.java:不變
public class Mainclass{
    public static void main(String[] args){
        /**
         * 經過工廠類的靜態方法實例化
         */
        Fruit apple = FruitFactory.getApple();
        Fruit banana = FruitFactory.getBanana();

        apple.get();
        banana.get();
    }
}

方式四:優化工廠類一,調用相同的方法,經過傳參的方式實例化

FruitFactory:
public class FruitFactory {
    public static Fruit getFruit(String type) throws IllegalAccessException, ClassNotFoundException, InstantiationException {
        /**
         * 對參數的判斷並返回實例
         */
        if (type.equalsIgnoreCase("apple")){
            return Apple.class.newInstance();
        } else if (type.equalsIgnoreCase("banana")){
            return Banana.class.newInstance();
        } else {
            System.out.println("找不到相應的實例化類");
            return null;
        }
    }
}
Fruit.java:不變
public interface Fruit {
    public void get();
}
Apple.java:不變
public class Apple implements Fruit{
    @Override
    public void get(){
        System.out.println("採集蘋果");
    }
}
Banana.java:不變
public class Banana implements Fruit{
    @Override
    public void get(){
        System.out.println("採集香蕉");
    }
}
MainClass.java:
public class Mainclass{
    public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, InstantiationException {
        Fruit apple = FruitFactory.getFruit("apple");
        Fruit banana = FruitFactory.getFruit("banana");
        apple.get();
        banana.get();
    }
}

方式五:優化工廠類二,經過反射類名進一步優化實例化過程

FruitFactory:
public class FruitFactory {
    public static Fruit getFruit(String type) throws IllegalAccessException, ClassNotFoundException, InstantiationException {
        
        Class fruit = Class.forName(type);
        return (Fruit)fruit.newInstance();
    }
}
Fruit.java:不變
public interface Fruit {
    public void get();
}
Apple.java:不變
public class Apple implements Fruit{
    @Override
    public void get(){
        System.out.println("採集蘋果");
    }
}
Banana.java:不變
public class Banana implements Fruit{
    @Override
    public void get(){
        System.out.println("採集香蕉");
    }
}
MainClass.java:
public class Mainclass{
    public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, InstantiationException {
        Fruit apple = FruitFactory.getFruit("Apple");
        Fruit banana = FruitFactory.getFruit("Banana");
        apple.get();
        banana.get();
    }
}

優勢

  • 工廠類含有必要的判斷邏輯,能夠決定在何時建立哪個產品類的實例,客戶端能夠免除直接建立產品對象的責任,而僅僅「消費」產品;簡單工廠模式經過這種作法實現了對責任的分割,它提供了專門的工廠類用於建立對象
  • 客戶端無須知道所建立的具體產品類的類名,只須要知道具體產品類所對應的參數便可,對於一些複雜的類名,經過簡單工廠模式能夠減小使用者的記憶量
  • 經過引入配置文件,能夠在不修改任何客戶端代碼的狀況下更換和增長新的具體產品類,在必定程度上提升了系統的靈活性
  • 當須要引入新的產品是不須要修改客戶端的代碼,只須要添加相應的產品類並修改工廠類就能夠了,因此說從產品的角度上簡單工廠模式是符合「開-閉」原則的

缺點

  • 因爲工廠類集中了全部產品建立邏輯,工廠類通常被咱們稱做「全能類」或者「上帝類」,由於全部的產品建立他都能完成,這看似是好事,但仔細想一想是有問題的。好比全國上下全部的事情都有國家主義一我的幹會不會有問題,固然有!一旦不能正常工做,整個系統都要受到影響
  • 使用簡單工廠模式將會增長系統中類的個數,在必定程序上增長了系統的複雜度和理解難度
  • 系統擴展困難,一旦添加新產品就不得不修改工廠邏輯,在產品類型較多時,有可能形成工廠邏輯過於複雜,不利於系統的擴展和維護。因此說從工廠的角度來講簡單工廠模式是不符合「開-閉」原則的
  • 簡單工廠模式因爲使用了靜態工廠方法,形成工廠角色沒法造成基於繼承的等級結構

適用場景

  1. 工廠類負責建立的對象比較少:因爲建立的對象較少,不會形成工廠方法中的業務邏輯太過複雜
  2. 客戶端只知道傳入工廠類的參數,對於如何建立對象不關心:客戶端既不須要關心建立細節,甚至連類名都不須要記住,只須要知道類型所對應的參數
相關文章
相關標籤/搜索