享元设计模式coding
生活随笔
收集整理的這篇文章主要介紹了
享元设计模式coding
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
我們來coding享元模式,享元模式的重點就是共享,網站需要各個管理者上傳報告,如果這些報告已經生成過了,我們就沒有必要再去new一個了,我們來通過這場景來體現一下享元模式,這里面我們也會結合工廠模式,首先我們創建一個包,結構型,這里創建一個享元的包,flyweight,flyweight英文的愿意呢,是指輕量級的,如果用英英字典來解析的話,最輕量級的類,那在中文翻譯成享元模式,還是非常貼切的,那我們首先創建一個員工的接口
首先看這三個類,下面的應用層先不看,這個關系還是非常簡單的,重點在這個工廠中,EMPLOYEE_MAP,然后他兩是組合關系,EmployeeFactory的getManager的返回值,是Employee,然后他來創建對應的Manager,Manager又實現Employee,那整體來說,享元模式理解起來也非常容易,那我們也強調了,在使用享元模式的時候,我們一定要關注線程安全問題,例如說現在這個Test,那在getManager的時候,這里面使用的就是HashMap,并不是線程安全的,而且我們這里面也沒有加同步鎖,那對于作報告這種簡單的場景,如果我們多線程過來的時候,其實并沒有必要關注他的線程安全問題,我們說的線程安全問題,其實也是要享元模式一定要保證他的線程安全,這個還是要根據實際的應用場景進行取舍,那現在我們來思考一下,對于這個部門經理,department這個屬性,現在是聲明在外部的,Manager的department屬性,它是在外部來聲明的,并且Manager的department的狀態依賴于外部傳入的一個參數,所以我們可以認為他是外部狀態,因為我傳入不同的department,所獲得的這個Manager,他里面的department的屬性是不一樣的,對于Manager這個實體,我們就可以認為這個狀態department這個狀態,是外部狀態,那怎么理解內部狀態,很簡單,我們寫一個private String title,直接賦值部門經理,這個時候我們外部怎么傳department,或者reportContent,Manager的title是不變的,他不隨外部的department的狀態變化而變化,他的title永遠是部門經理,非常容易理解,之所以把title放到這里面講,而不是之前講呢,是因為前面我們也有說,大家在coding的時候呢,就開始思考,然后在這里面我們再強調一下,并且產生對比,這樣你們對外部狀態和內部狀態肯定會理解的,那這種例子非常多,假設我們現在要用程序,畫圓形,而這個圓形的半徑,如果我們是固定好的,那他就是內部狀態,如果這個圓形的半徑需要我們在應用層,客戶端代碼來傳入的話,那么他就是外部狀態,那我們再思考一個問題,如果這個圓形還要有顏色呢,希望你們能繼續思考一下,非常簡單,那享元模式就講到這里,我們看一下享元模式在一些源碼的應用
package com.learn.design.pattern.structural.flyweight;/*** 這個接口我們有一個方法report* 部門的Manager當然也是員工* 他實現員工這個接口之后呢* 也就要實現report接口* 我們再創建一個類* Manager* * @author Leon.Sun**/
public interface Employee {/*** 做報告* * */void report();
}
package com.learn.design.pattern.structural.flyweight;/*** 實現Employee* 然后實現他的接口* 既然是部分的Manager* 他的屬性就是所在的部門* * * @author Leon.Sun**/
public class Manager implements Employee {/*** 那在report的時候就比較簡單了* 因為報告的內容我已經拿到了* 所以我們直接輸出* reportContent* 開始做報告* 那這兩個映射類OK了* 我們還要創建一個類呢* 是工廠* 通過Employee的工廠呢* 來獲取對應的Manager* 對應的Employee* 那我們這里只關注Manager* 因為現在只讓Manager做報告* 我們Employee不需要做報告* * */@Overridepublic void report() {System.out.println(reportContent);}private String title = "部門經理";/*** 部門*/private String department;/*** 那在做報告的時候* 需要有內容的* 所以他還持有一個報告的內容* reportContent* 這么兩個屬性* 那這個Manager在new的時候* 我肯定是應該知道* 他在哪個部門的* * */private String reportContent;/*** 那對于reportContent* 我們可以在外部重置reportContent* 所以我們加一個reportContent的set方法* * * @param reportContent*/public void setReportContent(String reportContent) {this.reportContent = reportContent;}/*** 這里加一個構造器* 這個構造器只傳一個department就可以了* * * @param department*/public Manager(String department) {this.department = department;}
}
package com.learn.design.pattern.structural.flyweight;import java.util.HashMap;
import java.util.Map;/*** EmployeeFactory這個類是工廠類* 你們肯定是相當熟悉了* 之前有系統的學習過* 工廠相關的模式* 而且在單例模式中* 也學過容器單例* 所以這個類如何實現* 相信大部分是心里有數的* 那我們這一節就當一個復習* 非常簡單* 輕松加愉快的來學習享元模式* * * * @author Leon.Sun**/
public class EmployeeFactory {/*** 首先我們來創建一個容器* final的Map* key是String* value是Employee* 這個就叫EMPLOYEE_MAP* 因為我們使用static和final* IDEA會自動提示使用大寫的命名* 直接new一個HashMap* 然后泛型寫上* 我們都是用原生的JDK來做* 現在把Mape的包導入一下* * */private static final Map<String,Employee> EMPLOYEE_MAP = new HashMap<String,Employee>();/*** 我們再寫一個方法* 返回者肯定是這個類getManager* 就是需要從EMPLOYEE_MAP中獲取對應的Manager* Manager也是Employee* 接下來想要哪個經理來做報告* 這個部門我們就要交給外部來傳* 以后我們在使用的時候* 你們就要回想一下* 我們之前有講過內部狀態和外部狀態* 這個時候大家就可以跟著思考一下* 這個時候我們傳入一個入參* department* * * * @param department* @return*/public static Employee getManager(String department){/*** 然后獲取一個Manager* 直接從這里面獲得一個Manager* 賦值成什么呢* 肯定是從Map里面直接取* get的key肯定就是部門* 這里面需要我們強轉* * 首先從Map里面獲取一個Manager* * */Manager manager = (Manager) EMPLOYEE_MAP.get(department);/*** 這個時候做一些空判斷* 如果manager是空的話* * 如果沒有獲取到* 就new一個放進去* 如果我們還想讓同一部門的經理來做報告的話* 那我們直接從對象池中取出來* 就不需要new了* 接下來我們來寫一下主函數* Test測試類* * */if(manager == null){/*** 那我們就new一個manager出來* 把department傳進去* * manager現在有部門了* 那還需要讓他來創建報告* * */manager = new Manager(department);System.out.print("創建部門經理:"+department);/*** 然后把報告內容統一一下* * */String reportContent = department+"部門匯報:此次報告的主要內容是......";/*** 所以我們直接在這里面manager.setReportContent* 首先是部門名稱加上部門匯報* 誰來匯報* 此處的報告內容是* 開始做報告了* 那我們把這個順序改一下* 設置完報告呢* 就輸出一個創建報告* 然后reportContent放到這里邊* 這樣當這個經理第一次來做報告的時候* 首先我們這個系統要創建這個經理* 然后再創建這個報告* 都創建好之后* 放到這個對象池里邊* 下次做報告直接從池里拿* 不再走這個new的過程* 我們現在回到Test里邊* * */manager.setReportContent(reportContent);System.out.println(" 創建報告:"+reportContent);/*** 然后往EMPLOYEE_MAP中put* 把這個department和manager放進去* * */EMPLOYEE_MAP.put(department,manager);}/*** 直接return manager* 非常簡單* 那捋一下邏輯* * */return manager;}
}
package com.learn.design.pattern.structural.flyweight;/*** 也就是應用層的代碼* * * @author Leon.Sun**/
public class Test {/*** 首先我們聲明一個部門的常量* final的* 我們直接用一個String的數組就行* departments的一個數組* 這里面我們想象一下* 我們有研發部門* 還有呢QA部門* 還有PM部門* 還有BD部門* 其他的部門我們就不寫了* * */private static final String departments[] = {"RD","QA","PM","BD"};/*** 我們寫一個主函數* * * @param args*/public static void main(String[] args) {/*** 從這個部門隨機的取* 有一個for循環* * */for(int i=0; i<10; i++){/*** 首先我們有一個department* 這里面有一個隨機數從departments數組里隨機的取* 也就是說用這個數組的索引取隨機數* 這樣這個部門也就隨機了* 打個比方* 今天副總經理讓研發的Manager做報告* 過了幾天呢* 總經理又來說* 研發的經理過來* 大概年底的時間* 部門的Manager經常要做報告* 各種報告層出不窮* 所以這里還真的特別適合響應模式* 我們接著寫* 從departments里面直接取一個* 取一個下角標* Math.random()這個方法* 讓他乘上departments的length* 就OK了* 進行類型的轉換* 把它轉換成int* 這樣就從里面隨機的獲取元素* 來獲取這個部門的名稱* 然后Manager* * * */String department = departments[(int)(Math.random() * departments.length)];/*** 來獲取這個Manager* * EmployeeFactory.getManager* 把department傳進去* 這里面按照提示強轉一下* 那在Manager第一次做報告的時候* 報告還沒有準備好* 所以第一次的時候* 他需要new一個報告出來* 那以后就不需要new了* 就直接拿過來* 開始做匯報* 所以我們來到getManager這里邊* * * */Manager manager = (Manager) EmployeeFactory.getManager(department);/*** 做報告* * manager點report方法* 那么現在來run一下* 來看一下結果是什么樣子的* 我們看一下* 這里是10次的循環* 首先把QA的經理叫過來了* 讓他做報告* 他趕快創建一個報告* 主要是......* 而第二次的時候* 又讓他做一次報告* 他呢不需要再創建了* 我這里有現成的* 對于我們這個對象池我們這個經理也在* 他的報告也在* 那第三次叫BD的經理來做報告了* 然后連著讓他做兩次* 又叫QA的部門來做報告了* 他還是直接拿過來做報告* 然后叫PM的部門來做報告* 然后叫RD的部門來做報告* 那這些都是一樣的* 創建過程也是一樣的* 我們接著回來* 因為這里的代碼業務邏輯非常簡單* 就不領著一起來debug了* 而且我們在之前學習容器單例的時候* 這個知識點都有學過* 而且這里面的邏輯清晰而簡單* 那我們來解析一下他的類圖* * * */manager.report();}
// Integer a = Integer.valueOf(100);
// Integer b = 100;
//
// Integer c = Integer.valueOf(1000);
// Integer d = 1000;
//
// System.out.println("a==b:"+(a==b));
//
// System.out.println("c==d:"+(c==d));}
}
?
總結
以上是生活随笔為你收集整理的享元设计模式coding的全部內容,希望文章能夠幫你解決所遇到的問題。