01、靜態工廠方法替代構造器

来源:http://www.cnblogs.com/zhou-chao/archive/2017/10/13/7643159.html
-Advertisement-
Play Games

考慮用靜態工廠方法替代構造器 考慮使用靜態工廠方法來替代構造器的原因: 考慮下麵的程式: 該代碼的含義是返回一個很有可能是質數並且長度為3的BigInteger對像,這裡的長度只的是將整數裝換成二進位後的長度;很有可能指的是:不是質數的概率不超過2-100。 但是如果使用的是構造函數:BigInte ...


考慮用靜態工廠方法替代構造器


 考慮使用靜態工廠方法來替代構造器的原因:

  1. 靜態工廠方法有名稱:普通的構造器中,參數並不能很好地描述返回對象的特點,代碼的閱讀性不好。  

考慮下麵的程式:

Random random = new Random();
BigInteger integer = BigInteger.probablePrime(3, random);

 該代碼的含義是返回一個很有可能是質數並且長度為3的BigInteger對像,這裡的長度只的是將整數裝換成二進位後的長度;很有可能指的是:不是質數的概率不超過2-100

但是如果使用的是構造函數:BigInteger(int, Random),則很難通過參數來猜測返回的是什麼東西。


 2. 使用靜態工廠方法不需要每次調用的時候都創建一個新的對象。

如果一些不可變類在使用之前就已經創建好了實例,或者將構建好的實例緩存起來的話,那麼在實際使用的時候就能過直接拿過來用,避免了創建不必要的重覆對象,下麵還是通過已經實際應用的例子來看一下:

Boolean b = Boolean.valueOf(true);  

 這行代碼的含義就是創建一個值為true的Boolean對象,我們看一下它的源碼:

public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }

  而TRUE和FALSE的定義如下:

public static final Boolean TRUE = new Boolean(true);

public static final Boolean FALSE = new Boolean(false);

  很明顯,這兩個被直接定義成了不可變類,可以重覆使用。如果某些服務裡面需要經常創建相同的對象,並且創建對象的代價比較高,則使用這種方法可以顯著提高性能。


3. 使用靜態工廠方法可以返回原返回類型的任何子類型的對象。

如果API可以返回對象,但同時又不會是對象的類變成公有的,這種方法隱藏了實現類,同時也使API變得簡潔。

要說具體實例的話,Java Collections Framework的集合介面中,幾乎所有的實現都是通過一個靜態工廠方法在一個不可實例化的類中導出。

網路盜圖:

 服務提供者框架(Service Provider Framework)

作者提到:靜態工廠方法返回的對象所屬的類,在編寫該靜態工廠方法的類時可以不必存在。就是多個服務提供者實現一個服務,系統為服務提供者的客戶端提供多個實現,並把他們從多個實現中解耦出來。

服務提供者框架組件:服務介面(Service Interface)、提供者註冊API(Provider Registration API)、服務訪問API(Service Access API)以及可選組件 服務提供者介面(Service Provider Interface)。

感覺略難懂啊。。。biubiu~

對於JDBC:Connection是服務介面;DriverManager.RegisterDriver就是提供者註冊API;DriverManager.getConnection就是服務訪問API;Driver就是服務提供者介面。

(PS:是不是吧JDBC的東西忘了?還能手寫出來不?趕緊拿出小本本記下來。。。)

public static void main(String[] args) throws ClassNotFoundException, SQLException {
String URL = "jdbc:mysql://127.0.0.1:3306/study?useUnicode=true&characterEncoding=utf-8";
String USER = "root";//用戶名
String PASSWORD = "xxxxx";//你的MySQL密碼
//1.載入驅動程式
Class.forName("com.mysql.jdbc.Driver");
//2.獲得資料庫鏈接
Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
//3.通過資料庫的連接操作資料庫,實現增刪改查(使用Statement類)
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from user");
//4.處理資料庫的返回結果(使用ResultSet類)
while (rs.next()) {
System.out.println(rs.getString("username") + " " + rs.getInt("age"));
}
//關閉資源
rs.close();
st.close();
conn.close();
}

  稍微有點不太規範哈,不過功能是可以實現的。其中,如果使用了Maven來管理項目的話,需要添加:

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.44</version>
    </dependency>

  下麵還有一個具體的模板可供參考,以後可以直接拿過去稍微修改一下就可以用了,完美~:

//這是服務介面 Service Interface
public interface Service {
//各種方法
}

//這是服務提供者介面 Service Provider Interface
public interface Provider {
Service newService();
}

//這是一個不能直接實例化的類用來進行註冊和訪問的
public class Services {
private Services() { //禁止實例化
}

private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>();
public static final String DEAFULT_PROVIDER_NAME = "default";

//提供著註冊API Provider Registration API
public static void registerDefaultProvider(Provider provider) {
registerProvider(DEAFULT_PROVIDER_NAME, provider);
}
public static void registerProvider(String name, Provider provider) {
providers.put(name, provider);
}

//服務訪問API Service Access API
public static Service newInstance() {
return newInstance(DEAFULT_PROVIDER_NAME);
}
public static Service newInstance(String name) {
Provider provider = providers.get(name);
if (null == provider) {
throw new IllegalArgumentException("No Provider registered with name" + name);
}
return provider.newService();
}
}

 缺點

任何方法或多或少都會優缺點,沒有最好的方法,只有最合適的方法,對一個新的方法要全面瞭解其優缺點,然後根據自己的實際情況,選擇一個最合適的方法。

1、類如果不含公有的或者受保護的構造器的話,就不能夠被子類化,沒毛病啊~

2、其實靜態工廠方法跟其他靜態方法實際上沒啥區別,畢竟實現方法是類似的嘛~


 

靜態工廠方法常用的名稱,含義也比較直白:

  • valueOf:一般來說返回的實例跟參數有相同的值。
  • of:比valueOf更簡潔,含義類似。
  • getInstance:返回一個具體的實例,可以指定參數進行具體化區別。如果是單例(Singleton)的話,無參數,都返回唯一的實例。
  • getType: 字面意思,返回對象類型,so easy。

 

參考:Effective Java 中文版(第二版)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Moke測試學習總結: 被測試代碼: public class LoginPresenter { private UserManager mUserManager = new UserManager(); public void login(String username, String passw ...
  • sed是所謂的流編輯器,我們經常用它來做一些文本替換的事情,這是sed最擅長的事情,如sed 's/Bob/Tom/g'就是把文章中所有的Bob改成Tom。 sed是圖靈完備的,作為sed的粉絲,喜歡用sed做各種sed不擅長的事情,這裡實現一下wc -w的功能,也就是統計文章單詞數量。 我習慣喜歡 ...
  • 面試題 能不能自己寫個類叫java.lang.System? 答案:通常不可以,但可以採取另類方法達到這個需求。 解釋:為了不讓我們寫System類,類載入採用委托機制,這樣可以保證爸爸們優先,爸爸們能找到的類,兒子就沒有機會載入。而System類是Bootstrap載入器載入的,就算自己重寫,也總 ...
  • HashMap 的一些認識: (JDK 1.7) 基於哈希表的Map介面的非同步實現,定義了鍵映射到值的規則 此實現提供所有可選的映射操作,並允許使用null值和null鍵 此實現假定哈希函數將元素適當分佈在各桶之間,為讀取操作提供穩定性能 迭代時間與實例容量(桶的數量)及其大小(鍵-值映射關係數) ...
  • 本文分享網址: http://www.cnblogs.com/DesertHero2013/p/7662721.html 1)目標:通過一個屬性的線性組合;來進行預測模型。即: 其中 是 ;w和b學成後,模型就確定了。 其實 可以理解成各個屬性值的權值。 2)性能度量: 求出均方誤差並使它最小化,就 ...
  • require 的使用方法如 require("MyRequireFile.php"); 。這個函數通常放在 PHP 程式的最前面,PHP 程式在執行前,就會先讀入 require 所指定引入的文件,使它變成 PHP 程式網頁的一部份。常用的函數,亦可以這個方法將它引入網頁中。 include 使用 ...
  • eclipse 導出Runnable JAR file 導出後如果系統沒有JRE,雙擊無法運行,需要用命令方法 安裝後解決,如圖 雙擊後閃退的原因,通過執行 java -jar TingGe.jar ,發現如圖 原來所需要的圖片、聲音等內容雖然打包到其中,但是路徑差了一個新的命名層,內容都在包里,而 ...
  • jquery框架中提供了$.ajax、$.get、$.post方法,用於進行非同步交互,由於Django中預設使用CSRF約束,推薦使用$.get 示例:實現省市區的選擇 最終實現效果如圖: 將jquery文件拷貝到static/js/目錄下 打開booktest/views.py文件,定義視圖are ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...