設計模式-享元模式(Flyweight)
概述
- 定義 : 提供了減少物件數量從而改善應用所需的物件結構的方式
- 運用共享技術有效的支援大量細粒度的物件
- 型別 : 結構型
適用場景
- 常常應用於系統底層的開發, 以便解決系統的效能問題
- 系統有大量相似的物件, 需要緩衝池的場景
優點
- 減少物件的建立, 降低記憶體中物件的數量, 降低系統的記憶體, 提高效率
- 減少記憶體之外的其他資源佔用
缺點
- 關注內/外部狀態, 關注執行緒安全問題
- 使系統, 程式的邏輯複雜化
擴充套件
- 內部狀態
- 外部狀態
模式角色
-
Flyweight : 描述一個介面,通過這個介面f l y w e i g h t可以接受並作用於外部狀態
-
ConcreteFlyweight : 實 現 F l y w e i g h t 接 口 , 並 為 內 部 狀 態 ( 如 果 有 的 話 ) 增 加 存 儲 空 間 。
ConcreteFlyweight物件必須是可共享的。它所儲存的狀態必須是內部的;即,它必
須獨立於 ConcreteFlyweight物件的場景。 -
UNsharedConcreteFlyweight : 並非所有的F l y w e i g h t子類都需要被共享。 F l y w e i g h t介面使共享成為可能,但它並不強制共享。在F l y w e i g h t物件結構的某些層次, U n s h a r e d C o n c r e t e F l y w e i g h t物件通常將C o n c r e t e F l y w e i g h t物件作為子節點
-
FlyweightFactory
- 建立並管理Flyweight 物件。
- 確保合理地共享Flyweight當用戶請求一個Flyweight 時,F l y w e i g h t F a c t o r y物件提供一個已建立的例項或者建立一個(如果不存在的話)。
-
Client
- 維持一個對Flyweight 的引用。
- 計算或儲存一個(多個)Flyweight 的外部狀態。
程式碼實現
場景:
1.有一個員工介面Employee, 對應Flyweight介面
2.部門經理類Manger實現了員工介面, 對應ConcreteFlyweight介面實現
3. 一個EmployeeFactory類用於管理Employee, 對應FlyweightFactory
4. 場景就是部門經理做年終報告
程式碼如下 :
/**
* Flyweight角色
*
* @author 七夜雪
* @create 2018-11-23 18:52
*/
public interface Employee {
void report();
}
/**
* ConcreteFlyweight 角色
* @author 七夜雪
*/
public class Manager implements Employee {
@Override
public void report() {
System.out.println(reportContent);
}
// 這個就是內部狀態
private String title = "部門經理";
private String department;
private String reportContent;
public void setReportContent(String reportContent) {
this.reportContent = reportContent;
}
public Manager(String department) {
this.department = department;
}
}
/**
* FlyweightFactory角色
*
* @author 七夜雪
* @create 2018-11-23 14:07
*/
public class EmployeeFactory {
private static final Map<String,Employee> EMPLOYEE_MAP = new HashMap<String,Employee>();
public static Employee getManager(String department){
Manager manager = (Manager) EMPLOYEE_MAP.get(department);
if(manager == null){
manager = new Manager(department);
System.out.print("建立部門經理:"+department);
String reportContent = department+"部門彙報:此次報告的主要內容是......";
manager.setReportContent(reportContent);
System.out.println(" 建立報告:"+reportContent);
EMPLOYEE_MAP.put(department,manager);
}
return manager;
}
}
測試程式碼:
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();
}
}
測試結果:
建立部門經理:測試 建立報告:測試部門彙報:此次報告的主要內容是…
測試部門彙報:此次報告的主要內容是…
建立部門經理:開發 建立報告:開發部門彙報:此次報告的主要內容是…
開發部門彙報:此次報告的主要內容是…
建立部門經理:人力 建立報告:人力部門彙報:此次報告的主要內容是…
人力部門彙報:此次報告的主要內容是…
建立部門經理:產品 建立報告:產品部門彙報:此次報告的主要內容是…
產品部門彙報:此次報告的主要內容是…
人力部門彙報:此次報告的主要內容是…
產品部門彙報:此次報告的主要內容是…
開發部門彙報:此次報告的主要內容是…
人力部門彙報:此次報告的主要內容是…
開發部門彙報:此次報告的主要內容是…
人力部門彙報:此次報告的主要內容是…
從測試結果來看, 只有第一次使用時才建立了Manager物件, 其餘都是直接從Map中獲取了, 這就是享元模式的概念