java設計模式之享元設計模式
阿新 • • 發佈:2019-02-17
一.構成
單純享元模式
- 抽象享元角色:定義了公共的介面,所有的具體享元角色需要實現的介面,那些需要外蘊狀態的操作可以通過方法的引數傳入.
- 具體享元角色:實現抽線享元角色所規定的公共介面,如果有內蘊狀態的話必須負責為內蘊狀態提供儲存空間.享元內蘊狀態的屬性必須與物件所處的環境無關,也就是說內蘊狀態是不可以變化的.從而使得享元物件可以在系統中公用.
- 享元工廠角色:負責建立和管理享元角色,必須保證相同的外蘊狀態可以使用同一個享元角色.當一個客戶端帶者外蘊狀態來請求享元角色時,判斷該享元角色是否存在,如果有,就直接返回該存在的享元物件,如果沒有,就建立一個新的享元物件.
- 客戶端角色:需要維護所有享元角色的引用,維護所有的外蘊狀態.
複合享元模式
- 抽象享元角色:定義了公共的介面,所有的具體享元角色需要實現的介面,那些需要外蘊狀態的操作可以桶蓋方法的引數傳入.
- 具體享元角色(不同):實現抽線享元角色所規定的公共介面,如果有內蘊狀態的話必須負責為內蘊狀態提供儲存空間.享元內蘊狀態的屬性必須與物件所處的環境無關,也就是說內蘊狀態是不可以變化的.從而使得享元物件可以在系統中公用.
- 複合享元角色:複合享元角色由具體的享元角色構成,它不可以被共享.
- 享元工廠角色(不同):負責建立和管理享元角色,必須保證相同的外蘊狀態可以使用同一個享元角色.當一個客戶端帶者外蘊狀態來請求享元角色時,判斷該享元角色是否存在,如果有,就直接返回該存在的享元物件,如果沒有,就建立一個新的享元物件.
- 客戶端角色:需要維護所有享元角色的引用,維護所有具體享元角色的外蘊狀態.
二.程式碼
單純享元模式:例子(學生使用黃色的筆和藍色的筆,不需要每次使用都建立物件,而是在工廠中維護了這兩個物件)輸出 990368553===yel===語文作業public class MainTest { public static void main(String[] args) { IPen y1 = PenFactory.createIpen("yel"); IPen y2 = PenFactory.createIpen("yel"); IPen y3 = PenFactory.createIpen("yel"); IPen bule = PenFactory.createIpen("bule"); y1.write("語文作業"); y2.write("數學作業"); y3.write("英語作業"); bule.write("語文作業"); } } //抽象的享元角色 interface IPen { void write(String article); } // 具體的享元角色 class Pen implements IPen { private String color; public Pen(String color) { this.color = color; } @Override public void write(String article) { System.out.println(this.hashCode() + "===" + color + "===" + article); } } // 享元工廠角色 class PenFactory { private static final Map<String, IPen> map = new HashMap<>(); public static IPen createIpen(String color) { IPen iPen = map.get(color); synchronized (color) { if (iPen == null) { iPen = new Pen(color); map.put(color, iPen); } } return iPen; } }
990368553===yel===數學作業
990368553===yel===英語作業
1096979270===bule===語文作業 複合享元模式(就是把單純享元模式的多個物件組合起來,其中單純享元模式還是共享的,複合享元角色不能共享) 本人對這裡很不甚理解,如果有理解的大神求指點
public class MainTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("yel");
list.add("yel");
list.add("red");
ListPen listPen = PenFactory.createListPen(list);
listPen.write("語文作業");
}
}
//抽象的享元角色
interface IPen {
// 提供外蘊狀態
void write(String article);
}
// 具體的享元角色
class Pen implements IPen {
private String color;
public Pen(String color) {
this.color = color;
}
@Override
public void write(String article) {
System.out.println(this.hashCode() + "===" + color + "===" + article);
}
}
// 享元工廠角色
class PenFactory {
private static final Map<String, IPen> map = new HashMap<>();
// 建立單純享元角色
public static IPen createIpen(String color) {
IPen iPen = map.get(color);
synchronized (color) {
if (iPen == null) {
iPen = new Pen(color);
map.put(color, iPen);
}
}
return iPen;
}
// 建立複合享元角色
public static ListPen createListPen(List<String> colors) {
ListPen listPen = new ListPen();
for (String color : colors){
listPen.add(createIpen(color));
}
return listPen;
}
}
// 複合享元角色
class ListPen implements IPen{
private List<IPen> list = new ArrayList<>();
public void add(IPen iPen){
list.add(iPen);
}
@Override
public void write(String article) {
for (IPen iPen:list){
iPen.write(article);
}
}
}
輸出
990368553===yel===語文作業990368553===yel===語文作業
1096979270===red===語文作業
三.特點
- 解耦,把相同的屬性和不同的屬性抽取出來,而且物件的建立統一使用工廠來建立物件.
- 提高了記憶體的使用效率,在記憶體中建立的物件明顯減少,特別是在客戶端多次呼叫的時候,維護的物件大大的減少.
- 使得系統更加複雜,為了使得物件可以共享,需要將一些外部狀態抽取出來,這使得程式的邏輯複雜化.
- 物件的外部狀態,讀取外部的狀態使得執行時間稍長.
四.使用場景(滿足所有條件)
- 一個應用程式使用了大量的物件.
- 完全由於使用了大量的物件,造成很大的記憶體開銷
- 物件的大多數狀態都可以變為外蘊狀態
- 如果刪除物件的外部狀態,那麼可以用較少的共享物件取代很多組物件
- 應用程式不依賴物件標識