JAVA 設計模式之 工廠模式詳解


一、簡單工廠模式

  簡單工廠模式(Simple Factory Pattern)是指由一個工廠對象決定創建出哪一種產品類 的實例。屬於創建型模式,但它不屬於 GOF,23 種設計模式

(參考資料: http://en.wikipedia.org/wiki/Design_Patterns#Patterns_by_Type)。

  簡單工廠模式適用於的場景:

    1、適用 於工廠類負責創建的對象較少的場景,

      2、且客戶端只需要傳入工廠類的參數,對於如何創 建對象的邏輯不需要關心。

  簡單工廠模式缺點:

    1、工廠類的職業相對過重,增加新的產品時需要修改工廠類的判斷邏輯,違背開閉原則

    2、不易於擴展過於復雜的產品結構

 

下面手寫一個簡單的工廠模式

/**
 * @Description 需要實現的接口
 * @Author Bert
 * @Date 2019\5\21
 */
public interface ICoure {
    public void record();
}

/**
 * @Description 實現ICoure
 * @Author Bert
 * @Date 2019\5\21 0021
 */
public class JavaCoure implements ICoure {

    @Override
    public void record() {
        System.out.println("錄制Java課程!");
    }
}

/**
 * @Description 工廠類  將類的創建過程封裝到工廠里面
 * @Author Bert
 * @Date 2019\5\21 0021
 */
public class CourseFactory {
    /**
     * @Description 通過name判斷,創建對應的對象
     * @Date 2019\5\21 0021 23:05
     * @Param [name]
     * @return com.bert.simple.factory.ICoure
     */
    public ICoure create(String name){
        if("Java".equals(name))
            return new JavaCoure();
        if("Python".equals(name))
            return new PythonCoure();
        else
            return null;
    }
    /**
     * @Description //通過類的全路徑
     * @Date 2019\5\21 0021
     * @Param [className]
     * @return com.bert.simple.factory.ICoure
     */
    public ICoure create1(String className){
        try {
            if( null != className && !"".equals(className)){
                return (ICoure)Class.forName(className).newInstance();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @Description 傳入一個Class,可以避免輸入錯誤的內容
     * @Date 2019\5\21 0021
     * @Param [clazz]
     * @return com.bert.simple.factory.ICoure
     */
    public ICoure create2(Class clazz){
        if (null != clazz) {
            try {
                return (ICoure) clazz.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

/**
 * @Description 測試類
 * @Author Bert
 * @Date 2019\5\21 0021
 */
public class SimpleFactoryTest {

    public static void main(String[] args) {
        CourseFactory factory = new CourseFactory();
        /**
         * 通過簡單的工廠創建
         */
        ICoure iCoure = factory.create("Java");//方式1
        iCoure.record();

        ICoure factory1 = factory.create1("com.bert.simple.factory.JavaCoure");//方式2
        factory1.record();

        ICoure factory2 = factory.create2(JavaCoure.class);//方式3
        factory2.record();

    }
}

  簡單工廠模式在 JDK 源碼也是無處不在 現在我們來舉個例子:

/* 里面通過createCalendar(TimeZone zone, Locale aLocale)傳入時區、語言  創建不同時區的時間 */
        Calendar calendar = Calendar.getInstance();/* getInstance()是一個工廠模式,也是一個單例模式 */

//Calendar 源碼
public static Calendar getInstance()
    {
        return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    }

        /* getLogger(Class<?> clazz) 典型的工廠模式 */
        Logger logger = LoggerFactory.getLogger(SimpleFactoryTest.class);/*也是一個單例*/

//LoggerFactory源碼

public static Logger getLogger(Class<?> clazz) {
        Logger logger = getLogger(clazz.getName());
        if (DETECT_LOGGER_NAME_MISMATCH) {
            Class<?> autoComputedCallingClass = Util.getCallingClass();
            if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
                Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(), autoComputedCallingClass.getName()));
                Util.report("See http://www.slf4j.org/codes.html#loggerNameMismatch for an explanation");
            }
        }

        return logger;
    }

二、工廠方法模式

  工廠方法模式(Fatory Method Pattern)是指定義一個創建對象的接口,但讓實現這個 接口的類來決定實例化哪個類,工廠方法讓類的實例化推遲到子類中進行。屬於創建型模式,23中設計模式之一,在工廠方法 模式中用戶只需要關心所需產品對應的工廠,無須關心創建細節,而且加入新的產品符 合開閉原則。

 

/**
 * @Description 需要實現的接口
 * @Author Bert
 * @Date 2019\5\21
 */
public interface ICoure {
    public void record();
}

/**
 * @Description 實現ICoure
 * @Author Bert
 * @Date 2019\5\21 0021
 */
public class JavaCoure implements ICoure {

    @Override
    public void record() {
        System.out.println("錄制Java課程!");
    }
}

/**
 * @Description TODO
 * @Author Bert
 * @Date 2019\5\21 0021
 */
public class PythonCoure implements ICoure {

    @Override
    public void record() {
        System.out.println("錄制Python課程!");
    }
}

/**
 * @Description 工廠接口
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public interface ICoureFactory {
    ICoure create();
}

/**
 * @Description Java方法工廠
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public class JavaICoureFactory implements ICoureFactory{
    @Override
    public ICoure create() {
        return new JavaCoure();
    }
}

/**
 * @Description Python方法工廠
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public class PythonICoureFactory implements ICoureFactory{
    @Override
    public ICoure create() {
        return new PythonCoure();
    }
}

/**
 * @Description 工廠方法模式測試類
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public class FactoryMethodTest {

    public static void main(String[] args) {

        ICoureFactory iCoureFactory = new JavaICoureFactory();
        ICoure iCoure = iCoureFactory.create();
        iCoure.record();

        PythonICoureFactory iCoureFactory1 = new PythonICoureFactory();
        ICoure iCoure1 = iCoureFactory1.create();
        iCoure1.record();
    }
}

  類圖如下:

  工廠方法模式的適用場景:

    1、創建對象需要大量重復的代碼

    2、客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節,一個類通過其子類來指定創建哪個對象。

  工廠方法模式的優點:

    1、用戶只關系所需產品對應的工廠,無須關心創建細節。

    2、加入新產品符合開閉原則,提高了系統的可擴展性。

  工廠方法模式的缺點:

    1、類的個數容易過多,增加了代碼結構的復雜度。

    2、增加了系統的抽象性和理解難度。

三、抽象工廠模式

  抽象工廠模式(Abstract Factory Pattern)是指提供一個創建一系列相關或者相互依賴對象的接口,無須指定他們具體的類。

  屬於創建型設計模式。

  

/**
 * @Description 需要實現的接口
 * @Author Bert
 * @Date 2019\5\21
 */
public interface ICoure {
    public void record();
}

/**
 * @Description 實現ICoure
 * @Author Bert
 * @Date 2019\5\21 0021
 */
public class JavaCoure implements ICoure {

    @Override
    public void record() {
        System.out.println("錄制Java課程!");
    }
}

/**
 * @Description TODO
 * @Author Bert
 * @Date 2019\5\21 0021
 */
public class PythonCoure implements ICoure {

    @Override
    public void record() {
        System.out.println("錄制Python課程!");
    }
}

/**
 * @Description 要求所有的工廠都實現這個工廠
 *      一個品牌的抽象
 *      1、 抽象工廠不符合開閉原則 (在頂層接口中添加的抽象方法,在繼承他的類都需要繼承)
 *      2、擴展性強
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public interface ICouseeFactory {

    ICoure createCourse();

    Inote createNote();

    Ivideo createVideo();

}

/**
 * @Description TODO
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public interface Inote {

}

/**
 * @Description TODO
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public interface Ivideo {

}

/**
 * @Description TODO
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public class JavaNote implements Inote{
}

/**
 * @Description TODO
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public class JavaVideo implements Ivideo {
}

/**
 * @Description TODO
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public class PythonNote implements Inote {
}

/**
 * @Description TODO
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public class PythonVideo implements Ivideo {
}

/**
 * @Description JAVA 課程實現
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public class JavaCourseFactory implements ICouseeFactory {

    @Override
    public ICoure createCourse() {
        return new JavaCoure();
    }

    @Override
    public Inote createNote() {
        return new JavaNote();
    }

    @Override
    public Ivideo createVideo() {
        return new JavaVideo();
    }
}

/**
 * @Description Python課程實現
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public class PythonCourseFactory implements ICouseeFactory {

    @Override
    public ICoure createCourse() {
        return new PythonCoure();
    }

    @Override
    public Inote createNote() {
        return new PythonNote();
    }

    @Override
    public Ivideo createVideo() {
        return new PythonVideo();
    }
}

/**
 * @Description 抽象工廠 測試類
 * @Author Bert
 * @Date 2019\5\22 0022
 */
public class AbstactFactoryTest {
    public static void main(String[] args) {

        ICouseeFactory factory = new JavaCourseFactory();
        factory.createCourse().record();
        factory.createNote();
        factory.createVideo();

    }
}

 

  

 

  抽象工廠模式使用場景:

    1、客戶端(應用層)不依賴於產品類實例如何被創建,實現等細節。

    2、強調一系列相關的產品對象(屬於同一產品族)一起使用創建對象需要大量重復的代碼。

    3、提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體的實現。

  抽象工廠模式優點:

    1、具體產品在應用層代碼隔離,無須關系創建細節。

    2、將一個系列的產品族統一到一起創建。

  抽象工廠模式缺點:

    1、規定了所有可能被創建的產品集合,產品族中擴展新的產品困難,需要修改抽象工廠的接口。

    2、增加了系統的抽象性和理解難度。

 Spring 中用到的抽象工廠模式例如:DefaultListableBeanFactory

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM