1. 程式人生 > >設計模式之享元模式(Flyweight)

設計模式之享元模式(Flyweight)

設計模式之享元模式(Flyweight)

本篇為https://github.com/iluwatar/java-design-patterns/tree/master/flyweight閱讀筆記

場景

煉金術士的商店裡擺滿了魔法藥水。許多藥水是相同的,因此不需要為每個藥水建立新的物件。相反,一個物件例項可以表示多個貨架專案,因此記憶體佔用量仍然很小
它用於通過儘可能多地與類似物件共享來最小化記憶體使用或計算開銷。

藥水介面

public interface Potion {

    void drink();

}

解藥

public class HealPotion
implements Potion { @Override public void drink() { System.out.println("drink heal potion. @" + System.identityHashCode(this)); } }

毒藥

public class PoisonPotion implements Potion {
    @Override
    public void drink() {
        System.out.println("drink poison potion. @" +
System.identityHashCode(this)); } }

聖水

public class HolyWaterPotion implements Potion {
    @Override
    public void drink() {
        System.out.println("drink holy water potion. @" + System.identityHashCode(this));
    }
}

藥廠

public class PotionFactory {


    enum PotionType {
        POISON,
HEAL, HOLY_WATER; } public PotionFactory() { this.potions = new EnumMap<>(PotionType.class); } private final Map<PotionType, Potion> potions; public Potion createPotion(PotionType type) { Potion potion = potions.get(type); if (potion == null) { switch (type) { case HEAL: potion = new HealPotion(); potions.put(type,potion); break; case POISON: potion = new PoisonPotion(); potions.put(type,potion); break; case HOLY_WATER: potion = new HolyWaterPotion(); potions.put(type,potion); break; default: break; } } return potion; } }

藥房

public class Shop {

    private List<Potion> topShelf;
    private List<Potion> bottomShelf;

    public Shop() {
        topShelf = new ArrayList<>();
        bottomShelf = new ArrayList<>();
        fillShelf();
    }

    private void fillShelf() {
        PotionFactory factory = new PotionFactory();

        topShelf.add(factory.createPotion(PotionFactory.PotionType.HEAL));
        topShelf.add(factory.createPotion(PotionFactory.PotionType.HEAL));
        topShelf.add(factory.createPotion(PotionFactory.PotionType.POISON));
        topShelf.add(factory.createPotion(PotionFactory.PotionType.POISON));
        topShelf.add(factory.createPotion(PotionFactory.PotionType.HOLY_WATER));
        topShelf.add(factory.createPotion(PotionFactory.PotionType.HOLY_WATER));

        bottomShelf.add(factory.createPotion(PotionFactory.PotionType.HEAL));
        bottomShelf.add(factory.createPotion(PotionFactory.PotionType.HEAL));
        bottomShelf.add(factory.createPotion(PotionFactory.PotionType.POISON));
        bottomShelf.add(factory.createPotion(PotionFactory.PotionType.POISON));
        bottomShelf.add(factory.createPotion(PotionFactory.PotionType.HOLY_WATER));
        bottomShelf.add(factory.createPotion(PotionFactory.PotionType.HOLY_WATER));
    }

    public void enumerate() {
        System.out.println("===top===");
        for (Potion potion : topShelf) {
            potion.drink();
        }

        System.out.println("===bottom===");
        for (Potion potion : bottomShelf) {
            potion.drink();
        }
    }

}

測試

public class App {

    @Test
    public void flyweightTest(){
        Shop shop = new Shop();
        shop.enumerate();
    }
}

輸出

===top===
drink heal potion. @399573350
drink heal potion. @399573350
drink poison potion. @463345942
drink poison potion. @463345942
drink holy water potion. @195600860
drink holy water potion. @195600860
===bottom===
drink heal potion. @399573350
drink heal potion. @399573350
drink poison potion. @463345942
drink poison potion. @463345942
drink holy water potion. @195600860
drink holy water potion. @195600860

可以看到一共建立了三個物件

類圖

flyweight是一個通過與其他類似物件共享盡可能多的資料來最小化記憶體使用的物件; 當簡單的重複表示使用不可接受的記憶體量時,它是一種大量使用物件的方法。