目的
使用共享可以有效地支持大量细粒度对象。
说明
炼金术士的商店里摆满了魔法药水。许多药水是相同的,因此不需要为每个药水创建新的对象。相反,一个对象实例可以表示多个货架项目,因此内存占用空间很小
简而言之
它用于通过尽可能多地与类似对象共享来使内存使用最小化。
源码示例
从上面翻译我们的炼金术商店示例。首先,我们有不同的药水类型
public interface Potion { void drink(); }
public class HealingPotion implements Potion { private static final Logger LOGGER = LoggerFactory.getLogger(HealingPotion.class); @Override public void drink() { LOGGER.info("You feel healed. (Potion={})", System.identityHashCode(this)); } }
public class HolyWaterPotion implements Potion { private static final Logger LOGGER = LoggerFactory.getLogger(HolyWaterPotion.class); @Override public void drink() { LOGGER.info("You feel blessed. (Potion={})", System.identityHashCode(this)); } }
public class InvisibilityPotion implements Potion { private static final Logger LOGGER = LoggerFactory.getLogger(InvisibilityPotion.class); @Override public void drink() { LOGGER.info("You become invisible. (Potion={})", System.identityHashCode(this)); } }
|
然后是实际的Flyweight对象,它是用于创建药水的工厂
public class PotionFactory {
private final Map<PotionType, Potion> potions;
public PotionFactory() { potions = new EnumMap<>(PotionType.class); }
Potion createPotion(PotionType type) { Potion potion = potions.get(type); if (potion == null) { switch (type) { case HEALING: potion = new HealingPotion(); potions.put(type, potion); break; case HOLY_WATER: potion = new HolyWaterPotion(); potions.put(type, potion); break; case INVISIBILITY: potion = new InvisibilityPotion(); potions.put(type, potion); break; default: break; } } return potion; } }
|
它的用途如下
PotionFactory factory = new PotionFactory(); factory.createPotion(PotionType.INVISIBILITY).drink(); // You become invisible. (Potion=6566818) factory.createPotion(PotionType.HEALING).drink(); // You feel healed. (Potion=648129364) factory.createPotion(PotionType.INVISIBILITY).drink(); // You become invisible. (Potion=6566818) factory.createPotion(PotionType.HOLY_WATER).drink(); // You feel blessed. (Potion=1104106489) factory.createPotion(PotionType.HOLY_WATER).drink(); // You feel blessed. (Potion=1104106489) factory.createPotion(PotionType.HEALING).drink(); // You feel healed. (Potion=648129364)
|
适用场景
Flyweight模式的有效性在很大程度上取决于它的使用方式和位置。满足以下所有条件时应用Flyweight模式
- 应用程序使用大量对象
- 由于对象数量众多,存储成本很高
- 大多数对象状态可以是外部的
- 一旦外部状态被移除,许多对象组可被相对较少的共享对象替换
- 应用程序不依赖于对象标识。由于可以共享flyweight对象,因此对于概念上不同的对象,身份测试将返回true。