設計模式--第2篇(工廠模式)

一,工廠模式

工廠模式: 創建式模式的一種,由一個工廠對象決定創建出哪一種類的實例,即本身是一個創建對象的類,封裝了實例化對象的類;在開發中,當我們需要大量的創建某種類對象時,就可以考慮優先使用工廠模式;

二,原理類圖

1,工廠方法

在這裏插入圖片描述
意圖: 定義一個用於創建對象的接口,讓子類決定實例化哪一個類。Factory Method 使一個類的實例化延遲到其子類。
適用性:

  1. 當一個類不知道它所必須創建的對象的類的時候。
  2. 當一個類希望由它的子類來指定它所創建的對象的時候。
  3. 當類將創建對象的職責委託給多個幫助子類中的某一個,並且你希望將哪一個幫助子類是代理者這一信息局部化的時候。
2,抽象工廠

在這裏插入圖片描述
意圖: 提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
適用性:

  1. 一個系統要獨立於它的產品的創建、組合和表示時。
  2. 一個系統要由多個產品系列中的一個來配置時。
  3. 當你要強調一系列相關的產品對象的設計以便進行聯合使用時。
  4. 當你提供一個產品類庫,而只想顯示它們的接口而不是實現時。

三,實例

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,抽象工廠模式:

抽象工廠模式:

  1. 定義一個接口用於創建相關或有依賴關係的對象,不需要指明具體的類;
  2. 抽象工廠分爲抽象工廠和具體實現的工廠子類,我們可以根據創建的對象使用具體子類,完成需要的個性化功能;

工廠接口(即我們可能大量創建的對象種類的統一規範接口)

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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章