一,工廠模式
工廠模式: 創建式模式的一種,由一個工廠對象決定創建出哪一種類的實例,即本身是一個創建對象的類,封裝了實例化對象的類;在開發中,當我們需要大量的創建某種類對象時,就可以考慮優先使用工廠模式;
二,原理類圖
1,工廠方法
意圖: 定義一個用於創建對象的接口,讓子類決定實例化哪一個類。Factory Method 使一個類的實例化延遲到其子類。
適用性:
- 當一個類不知道它所必須創建的對象的類的時候。
- 當一個類希望由它的子類來指定它所創建的對象的時候。
- 當類將創建對象的職責委託給多個幫助子類中的某一個,並且你希望將哪一個幫助子類是代理者這一信息局部化的時候。
2,抽象工廠
意圖: 提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
適用性:
- 一個系統要獨立於它的產品的創建、組合和表示時。
- 一個系統要由多個產品系列中的一個來配置時。
- 當你要強調一系列相關的產品對象的設計以便進行聯合使用時。
- 當你提供一個產品類庫,而只想顯示它們的接口而不是實現時。
三,實例
1,簡單工廠模式:
簡單工廠模式: 工廠模式中最簡單,最常用的一種;
抽象類(即我們可能大量創建的對象種類規範)
package com.neei.factory;
/**
* @param
* @Author: AaNeei
* @Date: 2019/9/23 22:27
* @Description: 遊學網
* @throws:
*/
public abstract class Sql {
//連接
public abstract void connect();
//增
public void add(){
System.out.println("sql新增");
}
//刪
public void deleted(){
System.out.println("sql刪除");
}
//...
}
實現(即我們需要創建的具體細節類)
public class MySql extends Sql {
@Override
public void connect() {
System.out.println("連接到MySQL數據庫");
}
}
public class Oracle extends Sql {
@Override
public void connect() {
System.out.println("連接到Oracle數據庫");
}
}
public class SqlServer extends Sql {
@Override
public void connect() {
System.out.println("連接到SqlServer數據庫");
}
}
工廠(即統一暴露我們需要的種類的類)
package com.neei.factory;
import com.neei.factory.sql.MySql;
import com.neei.factory.sql.Oracle;
import com.neei.factory.sql.SqlServer;
import java.util.HashMap;
/**
* @param
* @Author: AaNeei
* @Date: 2019/9/23 22:25
* @Description: 遊學網
* @throws:
*/
public class SimpleFactory {
private static HashMap<String, Sql> map = new HashMap<>();
static {
map.put("mysql", new MySql());
map.put("sqlserver", new SqlServer());
map.put("oracle", new Oracle());
}
public static Sql getSqlFactory(String sqlType) {
return map.get(sqlType);
}
}
調用
public class FactoryClient {
public static void main(String[] args) {
Sql sql = SimpleFactory.getSqlFactory("mysql");
sql.connect();
}
}
2,工廠方法模式:
工廠方法模式: 將對象的實例化推遲到子類中;
抽象類(即我們可能大量創建的對象種類規範)
*/
public abstract class Connect {
public abstract void connectedTool(String sqlType);
private static HashMap<String, Sql> map = new HashMap<>();
static {
map.put("mysql", new MySql());
map.put("sqlserver", new SqlServer());
map.put("oracle", new Oracle());
}
public static Sql getSqlFactory(String sqlType) {
return map.get(sqlType);
}
}
實現(即我們需要創建的具體細節類)
public class IDB extends Connect {
@Override
public void connectedTool(String sqlType) {
System.out.println("通過IDB");
Connect.getSqlFactory(sqlType).connect();
}
}
public class Navicat extends Connect {
@Override
public void connectedTool(String sqlType) {
System.out.println("通過Navicat");
Connect.getSqlFactory(sqlType).connect();
}
}
public class SQLyog extends Connect {
@Override
public void connectedTool(String sqlType) {
System.out.println("通過SQLyog");
Connect.getSqlFactory(sqlType).connect();
}
}
工廠(即統一暴露我們需要的種類的類)
public class SimpleFactory {
private static HashMap<String, Sql> map = new HashMap<>();
static {
map.put("mysql", new MySql());
map.put("sqlserver", new SqlServer());
map.put("oracle", new Oracle());
}
public static Sql getSqlFactory(String sqlType) {
return map.get(sqlType);
}
}
調用
public class FactoryClient {
public static void main(String[] args) {
new IDB().connectedTool("mysql");
new SQLyog().connectedTool("oracle");
new Navicat().connectedTool("sqlserver");
}
}
3,抽象工廠模式:
抽象工廠模式:
- 定義一個接口用於創建相關或有依賴關係的對象,不需要指明具體的類;
- 抽象工廠分爲抽象工廠和具體實現的工廠子類,我們可以根據創建的對象使用具體子類,完成需要的個性化功能;
工廠接口(即我們可能大量創建的對象種類的統一規範接口)
public interface AbsFactory {
Sql connected(String sqlType);
//...
}
工廠(即我們需要創建的具體細節類的工廠)
public class IDB implements AbsFactory {
@Override
public Sql connected(String sqlType) {
System.out.println("通過IDB");
return Connect.getSqlFactory(sqlType);
}
}
public class Navicat implements AbsFactory {
@Override
public Sql connected(String sqlType) {
System.out.println("通過Navicat");
return Connect.getSqlFactory(sqlType);
}
}
public class SQLyog implements AbsFactory {
@Override
public Sql connected(String sqlType) {
System.out.println("通過SQLyog");
return Connect.getSqlFactory(sqlType);
}
}
實現(即我們需要創建的具體細節類)
public class MySql extends Sql {
@Override
public void connect() {
System.out.println("連接到MySQL數據庫");
}
}
public class Oracle extends Sql {
@Override
public void connect() {
System.out.println("連接到Oracle數據庫");
}
}
public class SqlServer extends Sql {
@Override
public void connect() {
System.out.println("連接到SqlServer數據庫");
}
}
調用
public class FactoryClient {
public static void main(String[] args) {
connected(new IDB());
connected(new Navicat());
connected(new SQLyog());
}
private static void connected(AbsFactory absFactory){
absFactory.connected("mysql").connect();
}
}
四,源碼分析
jdk源碼中使用的工廠模式,如**Calendar **;
public static Calendar getInstance(TimeZone zone,
Locale aLocale)
{
return createCalendar(zone, aLocale);
}
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;
}