java設計模式——享元模式


一. 定義與類型

定義:提供了減少對象數量從而改善應用所需的對象結構的方式,運用共享技術有效地支持大量細粒度的對象

類型:結構性

二. 使用場景

(1)  常常應用於系統底層的開發,以便解決系統的性能問題

(2)  系統有大量相似對象,需要緩沖池的場景

三. 優缺點

優點:

  (1) 減少對象的創建,降低內存中對象的數量,降低系統的內存,提高效率

  (2) 減少內存之外的其他資源占用

缺點:

  (1) 關注內/外狀態,關注線程安全問題

  (2) 使系統,程序的邏輯復雜化

四.享元——擴展

內部狀態

外部狀態

五. 相關設計模式

享元模式和代理模式

  代理模式就是代理一個類,如果生成這個代理類需要花費的資源和時間比較多,就可以使用享元模式,提高系統的速度

享元模式和單例模式

  單例模式中的容器單例就是享元模式的一種使用

六. Coding

以一個業務場景為例,假設每年年底的時候公司中的部門經理都需要寫年終報告,但是可能不止要報告一次,需要重復報告。

使用享元模式,可以很好的完成上面的例子。

先創建一個接口:

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2019-02-12 10:01
 **/
public interface Emplyee {
    void report();
}

再創建一個經理實體類,來實現接口

/**
 * @program: designModel
 * @description: 部門manager
 * @author: YuKai Fan
 * @create: 2019-02-12 10:01
 **/
public class Manager implements Emplyee {
    public void report() {
        System.out.println(reportContent);
    }
    private String title = "部門經理";
    private String department;//部門
    private String reportContent;//報告內容

    public Manager(String department) {
        this.department = department;
    }

    public void setReportContent(String reportContent) {
        this.reportContent = reportContent;
    }
}

在創建一個員工工廠,通過工廠在獲取manager,因為只需要manager做報告,不需要employee。

/**
 * @program: designModel
 * @description: 員工工廠
 * @author: YuKai Fan
 * @create: 2019-02-12 10:04
 **/
public class EmployeeFactory {
   //因為在享元模式中,一般要考慮線程安全問題,但是還是要看業務場景來使用
private static final Map<String, Emplyee> EMPLYEE_MAP = new HashMap<String, Emplyee>(); public static Emplyee getManager(String department) { Manager manager = (Manager) EMPLYEE_MAP.get(department); if (manager == null) { manager = new Manager(department); System.out.print("創建部門經理:" + department); String reportContent = department + "部門匯報:此次報告的主要內容是。。。。"; manager.setReportContent(reportContent); System.out.println(" 創建報告:" + reportContent); EMPLYEE_MAP.put(department, manager); } return manager; } }

應用層:

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2019-02-12 10:08
 **/
public class Test {
    private static final String departments[] = {"RD", "QA", "PM", "BD"};

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            String department = departments[(int) (Math.random() * departments.length)];
            Manager manager = (Manager) EmployeeFactory.getManager(department);
            manager.report();
        }
    }
}

結果:

UML類圖:

從結果可以看出,當部門經理做報告時只需要創建一次即可,下次不需要再次創建。減少了對象的創建

在上面的代碼例子中,department相當於外部狀態。因為它依賴於外部的傳入,為了方便理解,創建一個title屬性,它就是一個內部狀態,它不隨外部狀態department的變化而變化。

七. 源碼分析

(1)

Integer類就是典型的享元模式的例子

Integer.valueOf中有一個IntegerCache,上面的代碼中就對傳入的值進行判斷。如果是從IntegerCache中取出就直接返回,否則就new一個Integer對象。這也就是如果傳入的int值不在固定的范圍類,它們做==的時候一定是false,因為不是同一個對象。其中low=-128,high=127.

還有Long類的valueOf,也是同上的道理。

(2)

tomcat中的GenericObjectPoolConfig連接池

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM