場景
內存屬於稀缺資源,不要隨便浪費。如果有很多個完全相同或者相似的對象,我們可以通過享元模式來節省內存。
享元模式核心
享元模式以共享的方式高效的支持大量細粒度對象的重用。
享元對象能夠做到共享的關鍵是區分了內部狀態和外部狀態。內部狀態:可以共享,不會隨環境變化而變化;外部狀態:不可以共享,會隨環境變化而變化。
享元模式實現
FlyweightFactory享元工廠類:創建並管理享元對象,享元池一般設計成鍵值對。
Flyweight抽象享元類:通常是一個接口或抽象類,聲明公共方法,這些方法可以向外界提供對象的內部狀態,設置外部狀態。
ConcreteFlyweight具體享元類:爲內部狀態提供成員變量進行存儲。
UnsharedConcreteFlyweight非共享享元類:不能被共享的子類可以設計爲非共享享元類。
享元模式demo
在下圍棋的時候,每顆圍棋除了棋盤上所處位置不同,其他的特性都是相同的。顏色,形狀,大小可以定義爲可共享的內部狀態;位置定義爲不可共享的外部狀態。
定義享元類ChessFlyWeight,定義非共享享元類Coordinate展示棋子所在位置,定義具體享元類ConcreteChess來展示棋子的特性,定義享元工廠類ChessFlyWeightFactory。
public interface ChessFlyWeight {
void setColoe(String color);
String getColor();
void display(Coordinate c);
}
public class Coordinate {
private int x,y;
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
public class ConcreteChess implements ChessFlyWeight{
private String color;
public ConcreteChess(String color) {
this.color = color;
}
@Override
public void setColoe(String color) {
this.color = color;
}
@Override
public String getColor() {
return color;
}
@Override
public void display(Coordinate c) {
System.out.println("棋子顏色:" + color);
System.out.println("棋子位置:" + c.getX() + "----" + c.getY());
}
}
public class ChessFlyWeightFactory {
//享元池對象
private static Map<String, ChessFlyWeight> map = new HashMap <>();
public static ChessFlyWeight getChess(String color){
if (map.get(color) != null){
return map.get(color);
} else {
ChessFlyWeight chess = new ConcreteChess(color);
map.put(color, chess);
return chess;
}
}
}
public class Client {
public static void main(String[] args) {
//第一次測試,兩個對象相同
ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("黑色");
ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("黑色");
System.out.println(chess1);
System.out.println(chess2);
//第二次測試
System.out.println("增加外部狀態的處理====================");
chess1.display(new Coordinate(10,10));
chess2.display(new Coordinate(20,20));
}
}
結果如下所示,可以看到兩顆棋子是同一個對象(內部狀態相同),但是兩顆棋子所處的棋盤位置並不同(外部狀態不同):
享元模式類圖
享元模式開發中應用場景
享元模式由於其共享的特性,可以在任何“池”中操作,比如:線程池、數據庫連接池。
String類的設計也是享元模式
享元模式總結
優點:極大減少內存中對象的數量;相同或者相似對象內存中只存一份,極大的節約資源,提高系統性能;外部狀態相對獨立,不影響內部狀態。
缺點:模式較複雜,使程序邏輯複雜化;爲了節省內存,共享了內部狀態,分離出外部狀態,而讀取外部狀態使運行時間變長,用時間換取了空間。
以上爲享元模式的學習筆記,此文章爲尚學堂視頻的學習筆記+自己總結。