一、基本介紹
享元模式(結構型):運用共享技術來有効地支援大量細粒度對象的複用。它通過共享已經存在的對象來大幅度減少需要建立的對象數量、避免大量相似類的開銷,進而提高系統資源的使用率。
二、包含角色
1.抽象享元角色:為具體享元規範需要實作的公共接口,非享元的外部狀态以參數的形式通過方法傳入。
2.具體享元角色:實作抽象享元角色中所規定的接口,為需要共享的對象。
3.非享元角色:不共享的外部狀态,作為享元角色所需要的外部參數,以形參的方式傳入。
4.享元工廠角色:負責建立和管理享元角色,一般用緩存管理這些對象。
三、案例及UML類圖
案例說明:
驗證碼主要分為常見驗證碼,即數字+字母的形式,和計算類型驗證碼,即15+10=?類型的, 本公司主要提供驗證碼服務,其它要使用該服務的公司通過調用接口去建立使用該驗證碼, 因為通路量高,是以需要使用緩存來管理這些對象,節省記憶體開銷。
UML類圖:
類Captcha:
public interface Captcha {
/**
* 享元角色的公共接口
* @param captchaArgs 外部狀态,即變化的部分,通過參數傳遞,可以為對象或其它的參數。
*/
void product(CaptchaArgs captchaArgs);
}
說明:驗證碼接口,抽象享元角色,定義驗證碼公共接口。
類ComputeCaptcha:
public class ComputeCaptcha implements Captcha {
@Override
public void product(CaptchaArgs captchaArgs) {
System.out.println("生成了一個寬度:"+captchaArgs.getWidth()+"," +
"高度:"+captchaArgs.getHeight()+"複雜度:"+captchaArgs.getComplexity()+"的計算型驗證碼。");
}
}
說明:計算型驗證碼類,具體享元角色,需要共享的類。
類NormalCaptcha:
public class NormalCaptcha implements Captcha {
@Override
public void product(CaptchaArgs captchaArgs) {
System.out.println("生成了一個寬度:"+captchaArgs.getWidth()+"," +
"高度:"+captchaArgs.getHeight()+"複雜度:"+captchaArgs.getComplexity()+"的常見驗證碼。");
}
}
說明:常見的驗證碼,如輸入字母和數字的,具體享元角色,需要共享的類。
類CaptchaArgs:
public class CaptchaArgs {
public CaptchaArgs(Integer width, Integer height, String complexity) {
this.width = width;
this.height = height;
this.complexity = complexity;
}
private Integer width;
private Integer height;
/**
* 複雜度
*/
private String complexity;
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
public String getComplexity() {
return complexity;
}
public void setComplexity(String complexity) {
this.complexity = complexity;
}
}
說明:驗證碼參數類,非享元角色,用于接收驗證碼的外部變化參數。
類FlyweightFactory:
public class FlyweightFactory {
/**
* 享元角色的緩存,key是驗證碼的類型,都是單例的
*/
private Map<Integer, Captcha> captchaMap = new ConcurrentHashMap<>();
/**
* 初始化時,先添加好其需要共享的享元角色
*/
public FlyweightFactory() {
//0表示正常驗證碼
captchaMap.put(0,new NormalCaptcha());
//1表示輸入型驗證碼
captchaMap.put(1,new ComputeCaptcha());
}
/**
* 享元模式的擷取,隻傳回緩存中的,做到共享。
* @param type 類型,0是正常驗證碼。1是計算型驗證碼
* @return 驗證碼類
*/
public Captcha getCaptcha(int type) {
if(captchaMap.keySet().contains(type)) {
return captchaMap.get(type);
}else {
return null;
}
}
}
說明:驗證碼工廠,享元工廠,用一個緩存儲存需要共享的對象,為外部提供需要共享的變量。
類FlyweightTest:
public class FlyweightTest {
public static void main(String[] args) {
FlyweightFactory flyweightFactory = new FlyweightFactory();
//擷取一個正常驗證碼
Captcha captcha = flyweightFactory.getCaptcha(0);
// 生成一個長寬為120且簡單的正常驗證碼
captcha.product(new CaptchaArgs(120,120,"簡單"));
//擷取一個計算型驗證碼
captcha = flyweightFactory.getCaptcha(1);
// 生成一個長寬為200且複雜的計算型驗證碼
captcha.product(new CaptchaArgs(200,200,"複雜"));
}
}
說明:測試及用戶端類。
四、适用場景
1.系統中存在大量相同或相似的對象,這些對象耗費大量的記憶體資源。
2.常見的緩存
五、其它
注意:由于享元模式需要額外維護一個儲存享元的資料結構,是以應當在享元對象被使用得足夠多時才值得使用享元模式。