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; }
Calendar類圖java
Class.forName("com.mysql.jdbc.Driver");
@CallerSensitive public static Connection getConnection(String url) throws SQLException { java.util.Properties info = new java.util.Properties(); return (getConnection(url, info,Reflection.getCallerClass())); }
// Worker method called by the public getConnection() methods. private static Connection getConnection( String url, java.util.Properties info, Class<?> caller) throws SQLException { /* * When callerCl is null, we should check the application's * (which is invoking this class indirectly) * classloader, so that the JDBC driver class outside rt.jar * can be loaded from here. */ ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; synchronized(DriverManager.class) { // synchronize loading of the correct classloader. if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); } } if(url == null) { throw new SQLException("The url cannot be null", "08001"); } println("DriverManager.getConnection(\"" + url + "\")"); // Walk through the loaded registeredDrivers attempting to make a connection. // Remember the first exception that gets raised so we can reraise it. SQLException reason = null; for(DriverInfo aDriver : registeredDrivers) { // If the caller does not have permission to load the driver then // skip it. if(isDriverAllowed(aDriver.driver, callerCL)) { try { println(" trying " + aDriver.driver.getClass().getName()); Connection con = aDriver.driver.connect(url, info); if (con != null) { // Success! println("getConnection returning " + aDriver.driver.getClass().getName()); return (con); } } catch (SQLException ex) { if (reason == null) { reason = ex; } } } else { println(" skipping: " + aDriver.getClass().getName()); } } // if we got here nobody could connect. if (reason != null) { println("getConnection failed: " + reason); throw reason; } println("getConnection: no suitable driver found for "+ url); throw new SQLException("No suitable driver found for "+ url, "08001"); }
// Walk through the loaded registeredDrivers attempting to locate someone // who understands the given URL. for (DriverInfo aDriver : registeredDrivers) { // If the caller does not have permission to load the driver then // skip it. if(isDriverAllowed(aDriver.driver, callerClass)) { try { if(aDriver.driver.acceptsURL(url)) { // Success! println("getDriver returning " + aDriver.driver.getClass().getName()); return (aDriver.driver); } } catch(SQLException sqe) { // Drop through and try the next driver. } } else { println(" skipping: " + aDriver.driver.getClass().getName()); } }
由於這個能夠看出來它是一個for循環,在遍歷註冊的一個驅動,
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
而且它是CopyOnWriteArrayList,裏面是DriverInfo,初始化的時候他是一個空的,具體是何時完成註冊的呢, mysql
static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } }
public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da) throws SQLException { /* Register the driver if it has not already been added to our list */ if(driver != null) { registeredDrivers.addIfAbsent(new DriverInfo(driver, da)); } else { // This is for compatibility with the original DriverManager throw new NullPointerException(); } println("registerDriver: " + driver); }
if(driver != null) { registeredDrivers.addIfAbsent(new DriverInfo(driver, da)); }
此外,logback
中也有簡單工廠的影子。sql
public final class LoggerFactory public static ILoggerFactory getILoggerFactory() { }
最裏面有一個getLogger方法,數據庫
public static Logger getLogger(Class clazz) { return getLogger(clazz.getName()); } public static Logger getLogger(String name) { ILoggerFactory iLoggerFactory = getILoggerFactory(); return iLoggerFactory.getLogger(name); }
這個還有個重載,一個是String name,還有一個是Class clazz,clazz是幹嗎的,是clazz.getName(), 設計模式
首先getLogger根據咱們傳來的name,從iLoggerFactory裏面getLogger,先看一下 app
public interface ILoggerFactory package org.slf4j; //抽象產品工廠 public interface ILoggerFactory { //抽象工廠方法 public Logger getLogger(String name); }
很明顯ILoggerFactory它是一個接口,下面有一個方法,那這個呢是工廠方法,那在後面咱們也會講,這裏先過去, 框架
後面咱們學習工廠方法的時候,再單獨來講,而後經過iLoggerFactory.getLogger,由於它是一個接口,確定有多個實現,ide
LoggerContext //具體工廠實現類 public class LoggerContext extends ContextBase implements ILoggerFactory, LifeCycle { ... //具體工廠方法 @Override public final Logger getLogger(final String name) { ... }
這裏面咱們看一下,傳入的一個name,這裏面要返回Logger,這裏面對name進行了判斷,很明顯這個方法就是一個簡單工廠方法, 學習
根據傳入的入參進行選擇哪一個Logger,那這個仍是很是簡單的,剛剛也說了,在咱們的LoggerFactory裏面,既存在了工廠方法,ui
又存在了簡單工廠,因此設計模式在使用的時候,不必定要侷限在使用一種,例如這裏就是一個組合的使用,這個簡單工廠比較簡單,
在不少源碼中也可以找到他的影子,在前面的JDK,Logback開源框架的,對於學習設計模式的講解呢,咱們在閱讀源碼的時候呢,
還能夠以設計模式的角度,去聚焦源碼,這樣對咱們理解源碼也是有益處的 。