<input id="ohw05"></input>
  • <table id="ohw05"><menu id="ohw05"></menu></table>
  • <var id="ohw05"></var>
  • <code id="ohw05"><cite id="ohw05"></cite></code>
    <label id="ohw05"></label>
    <var id="ohw05"></var>
  • 設計模式:如何優雅地使用工廠模式

    本文從是什么、為什么、怎么做的三個步驟,分析簡單工廠模式、工廠方法模式和抽象工廠模式,通過框架源碼學習如何優雅地使用工廠模式。

    一、什么是工廠模式?

    關于什么是工廠模式這個問題呢?其實完全可以見名知意,工廠是做什么的?工廠是生產產品的地方啊,那么映射到編程領域,工廠模式不就是生產對象的一種模式嘛?借用百度百科的一句話來說:工廠模式是我們最常用的實例化對象模式了,是用工廠方法代替new操作的一種模式。

    工廠模式,按照業務實際場景可以劃分為3中不同的實現方式,分別是簡單工廠模式、工廠方法模式和抽象方法模式。

    簡單工廠模式又叫靜態工廠方法模式,簡單來說就是,該模式有一個具體的工廠類,可以生產許多不同的產品。有一件有意思的事情,簡單工廠模式其實不是一種設計模式(不屬于GoF23種設計模式),更像是一種編程等習慣,但是由于該習慣經常被使用,許多開發人員都把它稱為”工廠模式“,那么就”將錯就錯“被大家所接受咯。

    在簡單工廠模式中,生產產品是由一個單一的、具體的工廠類來實現的;在工廠方法模式中,不再采用這種方式,而是由工廠類的子類實現具體產品的生產工作。當增加一類產品的時候,只需要增加一個相應的工廠類的子類。這樣做的好處是可以解決簡單工廠模式由于生產產品種類過多而引發的代碼臃腫的問題。舉個例子,需要創建3種類型的產品,簡單工廠模式需要3個分支(不管是if-else也好,switch-case也罷),工廠方法模式需要3個子類;那么產品類型有10種呢?當生產的產品種類較多的時候,使用工廠方法模式可以解決簡單工廠方法模式大量代碼重復的問題,這也就是工廠方法模式存在的意義。

    抽象工廠模式是這么定義的:抽象工廠模式提供一個接口,用于創建相關或依賴對象的家族,而不需要明確執行具體類。抽象工廠允許客戶使用抽象的接口來創建一組相關的產品,而不需要關系實際產出的具體產品是什么。

    二、為什么使用工廠模式?

    ”為什么要使用工廠模式“,關于這個問題我是這么理解的:

    第一,為什么要使用設計模式?逼格,對,設計模式就是逼格的體現。除了逼格,說的實際點,就是可以使代碼變得清晰和優雅,讓新人接手代碼的時候在心里少罵我們幾句。

    第二,主要的目的還是解耦。如果沒有簡單工廠模式,我們需要關心生產邏輯(創建過程)和調用,可以使用一坨代碼去實現,此時這二者是沒有分開的;當使用了簡單工廠模式,具體的生產邏輯放在了簡單工廠里面,只需要調用即可;當品類增多,簡單工廠的工廠類的邏輯變得復雜,耦合變得嚴重,出現工廠方法模式,將不同品類的生產邏輯剝離到子類中進行,讓外部只是知道如何調用即可,實現解耦....其實從不使用設計模式--> 簡單工廠模式--> 工廠方法模式-->抽象工廠模式,這就是層次遞進的解耦關系。那為什么需要使用工廠模式呢,我想本質也就在這里吧。

    三、如何優雅地使用工廠模式?

    關于如何使用工廠模式?不寫之前的demo了,來看下優秀的框架中是如何使用工廠模式的。

    3.1 簡單工廠模式

    簡單工廠模式java.util.Calendar類中的運用:

    private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }
    
        Calendar cal = null;
    
        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                switch (caltype) {
                case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
        if (cal == null) {
            // If no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }
    

    3.2 工廠方法模式

    Logback源碼中的工廠方法模式的使用:

    public static Logger getLogger(String name){
        ILoggerFactory iLoggerFactory = getILoggerFactory();
        return iLoggerFactory.getLogger(name);
    }
    public static Logger getLogger(Class clazz){
        return getLogger(clazz.getName());
    }
    

    3.3 抽象方法模式

    在Spring源碼中,所有工廠都是BeanFactory的子類。通過對BeanFactory的實現,我們可以從Spring的容器訪問Bean。根據不同的策略調用getBean()方法,從而獲得具體對象。

    public interface BeanFactory {
        String FACTORY_BEAN_PREFIX = "&";
    
        Object getBean(String var1) throws BeansException;
    
        <T> T getBean(String var1, Class<T> var2) throws BeansException;
    
        Object getBean(String var1, Object... var2) throws BeansException;
    
        <T> T getBean(Class<T> var1) throws BeansException;
    
        <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
    
        <T> ObjectProvider<T> getBeanProvider(Class<T> var1);
    
        <T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
    
        boolean containsBean(String var1);
    
        boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
    
        boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
    
        boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
    
        boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
    
        @Nullable
        Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
    
        @Nullable
        Class<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;
    
        String[] getAliases(String var1);
    }
    
    posted @ 2020-11-28 22:47  James_Shangguan  閱讀(441)  評論(0編輯  收藏  舉報
    国产美女a做受大片观看