場(chǎng)景
內(nèi)存屬于稀缺資源,不要隨便浪費(fèi)。如果有很多完全相同或相似的對(duì)象,我們可以通過享元模式,節(jié)省內(nèi)存。
核心
- 享元模式以共享的方式高效地支持大量細(xì)粒度對(duì)象的重用。
- 享元對(duì)象能做到共享的關(guān)鍵是區(qū)分了內(nèi)部狀態(tài)和外部狀態(tài)。
內(nèi)部狀態(tài):可以共享,不會(huì)隨環(huán)境變化而改變
外部狀態(tài):不可以共享,回隨環(huán)境變化而改變
享元模式實(shí)現(xiàn)
- FlyweightFactory享元工廠類
創(chuàng)建并管理享元對(duì)象,享元池一般設(shè)計(jì)成鍵值對(duì) - Flyweight抽象享元類
通常是一個(gè)接口或抽象類,聲明公共方法,這些方法可以向外界提供對(duì)象的內(nèi)部狀態(tài),設(shè)置外部狀態(tài) - ConcreteFlyweight具體享元類
為內(nèi)部狀態(tài)提供成員變量進(jìn)行儲(chǔ)存 -
UnsharedConcreteFlyweight非共享享元類
不能被共享的子類可以設(shè)計(jì)為非共享享元類
享元模式
package flyweight;
// 以圍棋為例
// Flyweight
public interface Chess {
String getColor();
void display(Coordinate c);
}
// ConcreteFlyweight
class ConcreteChess implements Chess{
private String color;
public ConcreteChess(String color) {
this.color = color;
}
public String getColor() {
return color;
}
public void display(Coordinate c) {
System.out.println("顏色:"+color);
System.out.println("位置:("+c.getX()+","+c.getY()+")");
}
}
// UnsharedConcreteFlyweight
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;
}
}
package flyweight;
import java.util.HashMap;
import java.util.Map;
// FlyweightFactory
public class ChessFactory {
private static Map<String,Chess> map = new HashMap<String, Chess>();
public static Chess getChess(String color){
if (map.get(color) != null){
return map.get(color);
}else{
Chess chess = new ConcreteChess(color);
map.put(color,chess);
return chess;
}
}
}
package flyweight;
public class Client {
public static void main(String[] args) {
Chess chess = ChessFactory.getChess("黑色");
Chess chess1 = ChessFactory.getChess("黑色");
System.out.println(chess);
System.out.println(chess1);
System.out.println("=====增加外部狀態(tài)=====");
chess.display(new Coordinate(10,10));
chess1.display(new Coordinate(20,20));
}
}
輸出:
flyweight.ConcreteChess@4edf9252
flyweight.ConcreteChess@4edf9252
=====增加外部狀態(tài)=====
顏色:黑色
位置:(10,10)
顏色:黑色
位置:(20,20)
享元模式開發(fā)中應(yīng)用的場(chǎng)景:
- 享元模式由于其共享的特性,可以在任何"池"中操作,比如線程池、數(shù)據(jù)庫(kù)連接池。
- String類的設(shè)計(jì)也是享元模式
優(yōu)點(diǎn)
- 極大減少內(nèi)存中對(duì)象的數(shù)量
- 相同或相似對(duì)象內(nèi)存中只存一份,極大節(jié)約資源,提高系統(tǒng)性能
- 外部狀態(tài)相對(duì)獨(dú)立,不影響內(nèi)部狀態(tài)
缺點(diǎn)
- 模式較復(fù)雜,是程序邏輯復(fù)雜化
- 為了節(jié)省內(nèi)存,共享了內(nèi)部狀態(tài),分離出外部狀態(tài),而讀取外部狀態(tài)使運(yùn)行時(shí)間變長(zhǎng)。用時(shí)間換取了空間。
何時(shí)使用
如果一個(gè)應(yīng)用程序使用了大量的對(duì)象,而大量的這些對(duì)象造成了很大的存儲(chǔ)開銷時(shí)就應(yīng)該考慮使用;還有就是對(duì)象的大多數(shù)狀態(tài)可以外部狀態(tài),如果刪除對(duì)象的外部狀態(tài),那么可以用相對(duì)較少的共享對(duì)象取代很多組對(duì)象,此時(shí)可以考慮使用享元模式。
