天天看點

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

簡單工廠模式

概念

簡單工廠模式屬于建立型模式,又叫做靜态工廠方法(Static Factory Method)。簡單工廠模式是由一個工廠對象決定建立哪一種産品類執行個體。在簡單工廠模式中,可以根據參數的不同傳回不同類的執行個體。簡單工廠模式專門定義一個類來負責建立其他類的執行個體,被建立的執行個體通常都具有共同的父類。簡單工廠模式是工廠模式家族中最簡單實用的模式,可以了解為不同工廠模式的一個特殊實作

值得注意的是,簡單工廠模式并不屬于GOF設計模式之一。但是他說抽象工廠模式,工廠方法模式的基礎,并且有廣泛得應用

模式結構

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

組成

從上圖中可以看出,簡單工廠模式由三部分組成:具體工廠、抽象産品和具體産品:

  • 工廠類(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. 用戶端隻知道傳入工廠類的參數,對于如何建立對象不關心:用戶端既不需要關心建立細節,甚至連類名都不需要記住,隻需要知道類型所對應的參數

繼續閱讀