天天看點

Java 設計模式-享元模式(Flyweight)

    享元模式(Flyweight Pattern)是對象的結構模式。享元模式以共享的方式高效地支援大量細粒度對象的建立。

   享元對象能夠做到共享的關鍵是區分内蘊狀态和外蘊狀态;内蘊狀态就是指不随環境的改變而改變、可以共享的狀态,外蘊狀态是随環境的改變而改變,不可以共享的狀态;因為外蘊狀态不可以共享是以外蘊狀态的儲存時由用戶端進行儲存的,在需要的時候再傳入到享元對象内部。

   在日常的編輯器中,字型的大小樣式都是可以改變的,但是字元是的值是一直不變的;輸入的A,不管是斜體的還是黑體的它永遠都是A。由此可以發現A的值是一個内蘊狀态,而A的字型樣式是一個外蘊狀态。

/**
 *   字母的抽象接口
 * @author zhangwei_david
 * @version $Id: Letter.java, v 0.1 2015年3月26日 下午3:51:13 zhangwei_david Exp $
 */
public interface Letter {

    public void resetFont(String font);
}
           
/**
 *
 * @author zhangwei_david
 * @version $Id: Character.java, v 0.1 2015年3月26日 下午3:59:01 zhangwei_david Exp $
 */
public class Character implements Letter {

    private String value;

    public Character(String value) {
        super();
        this.value = value;
    }

    /**
     * @see com.pattern.create.flyweight.Letter#resetFont(java.lang.String)
     */
    @Override
    public void resetFont(String font) {
        System.out.println("字元" + value + "的字型是" + font);
    }

}
           
/**
 *
 * @author zhangwei_david
 * @version $Id: CharacterFactory.java, v 0.1 2015年3月26日 下午4:09:01 zhangwei_david Exp $
 */
public class CharacterFactory {

    private Map<String, Letter>     characters = new HashMap<String, Letter>();

    private static CharacterFactory instance   = new CharacterFactory();

    public static CharacterFactory getInstance() {
        return instance;
    }

    public Letter factory(String value) {
        if (characters.containsKey(value)) {
            return characters.get(value);
        }
        Letter letter = new Character(value);
        characters.put(value, letter);
        return letter;
    }

    public int getObjectSize() {
        return characters.size();
    }
}
           
/**
 *
 * @author zhangwei_david
 * @version $Id: Client.java, v 0.1 2015年3月26日 下午4:14:01 zhangwei_david Exp $
 */
public class Client {

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        CharacterFactory characterFactory = CharacterFactory.getInstance();
        Letter letter1 = characterFactory.factory("a");
        letter1.resetFont("斜體 10号");

        Letter letter2 = characterFactory.factory("a");
        letter2.resetFont("黑體 10号");
        System.out.println(characterFactory.getObjectSize());
    }

}
           
字元a的字型是斜體 10号
字元a的字型是黑體 10号
1
           

 可以發現實際建立的對象隻有一個,而表象是兩個

   通過享元模式的定義可以發現不可變對象是天生的享元對象,所有雖說享元對象不一定是不可變的,但是往往将享元對象設計為一個不可變的對象。

什麼時候使用享元模式

  1. 一個系統中有大量的對象
  2. 這些對象往往消耗大量記憶體資源
  3. 這些對象中的狀态中大部分都可以外部化
  4. 這些對象可以按照内蘊狀态可以分為很多組,當把外蘊狀态從對象中剔除時,每一組可以僅适用一個對象替代
  5. 系統不依賴于這些對象的身份,換言之這些對象是不可分辨的。

當滿足以上情況就可以使用享元模式。