什么是享元(Flyweight)模式?
享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
享元模式的主要优点是:相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
其主要缺点是:
为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。
读取享元模式的外部状态会使得运行时间稍微变长。
例子
在这个例子中{@link alchemishop(药剂商店)}的货架上有大量的药剂。填充
shelves(货架){@link alchemischeshop(药剂商店)}使用{@link PotionFactory(药剂工厂)}(它代表了这个页面中的Flyweight)
示例)。在内部{@link PotionFactory}保存了一个药剂的列表。可以很方便的创建。
public class App {
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) {
var alchemistShop = new AlchemistShop();
alchemistShop.enumerate();
}
}
/**
* AlchemistShop holds potions on its shelves. It uses PotionFactory to provide the potions.
*/
public class AlchemistShop {
private static final Logger LOGGER = LoggerFactory.getLogger(AlchemistShop.class);
private final List<Potion> topShelf;
private final List<Potion> bottomShelf;
/**
* Constructor.
*/
public AlchemistShop() {
var factory = new PotionFactory();
topShelf = List.of(
factory.createPotion(PotionType.INVISIBILITY),
factory.createPotion(PotionType.INVISIBILITY),
factory.createPotion(PotionType.STRENGTH),
factory.createPotion(PotionType.HEALING),
factory.createPotion(PotionType.INVISIBILITY),
factory.createPotion(PotionType.STRENGTH),
factory.createPotion(PotionType.HEALING),
factory.createPotion(PotionType.HEALING)
);
bottomShelf = List.of(
factory.createPotion(PotionType.POISON),
factory.createPotion(PotionType.POISON),
factory.createPotion(PotionType.POISON),
factory.createPotion(PotionType.HOLY_WATER),
factory.createPotion(PotionType.HOLY_WATER)
);
}
/**
* Get a read-only list of all the items on the top shelf.
*
* @return The top shelf potions
*/
public final List<Potion> getTopShelf() {
return List.copyOf(this.topShelf);
}
/**
* Get a read-only list of all the items on the bottom shelf.
*
* @return The bottom shelf potions
*/
public final List<Potion> getBottomShelf() {
return List.copyOf(this.bottomShelf);
}
/**
* Enumerate potions.
*/
public void enumerate() {
LOGGER.info("Enumerating top shelf potions(列举顶级药水)\n");
topShelf.forEach(Potion::drink);
LOGGER.info("Enumerating bottom shelf potions(列举底层药水)\n");
bottomShelf.forEach(Potion::drink);
}
}
/**
* PotionFactory is the Flyweight in this example. It minimizes memory use by sharing object
* instances. It holds a map of potion instances and new potions are created only when none of the
* type already exists.
*/
public class PotionFactory {
private final Map<PotionType, Potion> potions;
public PotionFactory() {
potions = new EnumMap<>(PotionType.class);
}
Potion createPotion(PotionType type) {
var 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;
case POISON:
potion = new PoisonPotion();
potions.put(type, potion);
break;
case STRENGTH:
potion = new StrengthPotion();
potions.put(type, potion);
break;
default:
break;
}
}
return potion;
}
}
/**
* Interface for Potions.
*/
public interface Potion {
void drink();
}
/**
* HealingPotion.
*/
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));
}
}
/**
* HolyWaterPotion.
*/
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));
}
}
/**
* InvisibilityPotion.
*/
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));
}
}
/**
* PoisonPotion.
*/
public class PoisonPotion implements Potion {
private static final Logger LOGGER = LoggerFactory.getLogger(PoisonPotion.class);
@Override
public void drink() {
LOGGER.info("Urgh! This is poisonous(啊!这是有毒的). (Potion={})", System.identityHashCode(this));
}
}
/**
* StrengthPotion.
*/
public class StrengthPotion implements Potion {
private static final Logger LOGGER = LoggerFactory.getLogger(StrengthPotion.class);
@Override
public void drink() {
LOGGER.info("You feel strong(你感觉很坚强). (Potion={})", System.identityHashCode(this));
}
}
/**
* Enumeration for potion types.
*/
public enum PotionType {
HEALING, INVISIBILITY, STRENGTH, HOLY_WATER, POISON
}