三種工廠模式的詳解:
簡單工廠模式:
適用場景:工廠類負責創建的對象較少,客戶端只關心傳入工廠類的參數,對於如何創建對象的邏輯不關心
缺點:如果要新加產品,就需要修改工廠類的判斷邏輯,違背軟件設計中的開閉原則,且產品類多的話,就會使得簡單工廠類比較復雜
在jdk源碼中的具體實例(注意看代碼中的中文注釋)
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; }
除了日歷類還有JDBC,當我們需要MySQL數據庫的驅動時,我們就傳MySQL的參數,用Oracle的就傳相應的參數
工廠方法模式:
適用場景:創建對象需要大量重復代碼,客戶端不依賴與產品類實例如何被創建實現等細節,一個類通過其子類來指定創建哪個對象
工廠方法的核心在於把實例化過程放在子類中進行(這是和簡單工廠一個區別比較大的地方)
要解釋工廠方法模式,要有下面的概念:一個總的抽象工廠及抽象工廠的子類還有一個抽象的產品類與抽象產品類的子類,具體看下面的jdk源碼:

拿其中ArrayList實現的iterator()方法來看
public Iterator<E> iterator() { return new Itr(); } /** * An optimized version of AbstractList.Itr */ private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; }
可以這樣理解:Collection接口里面定義了許多方法就像size(),isEmpty(),iterator()等等這些方法可以認為是工廠里面的產品,Collection可以看作是一個總的抽象工廠。它的一些實現這個接口的類,像ArrayList,LinkedHashSet等等可以看作一個個不同的品牌的工廠,而總的產品Iterator接口里面會定義產品所需功能的細節,然后在交給各個品牌不同的工廠來實現。
抽象工廠模式:
看懂上面的之后就特別好理解抽象工廠,抽象工廠模式與工廠方法模式的最大區別就在於,工廠方法模式針對的是一個產品等級結構;(比如Iterator()方法的不同實現)而抽象工廠模式則需要面對多個產品等級結構(Collection接口下的不同方法)。再說明白一點就是:Collection就是一個抽象工廠,它提供了一個產品類的庫,所有產品都以同樣接口出現,從而使客戶端不依賴於具體實現。工廠方法則是抽象工廠里面的其中一個產品類,並且把這個方法的實例化放入具體的實現類中