一、概述
享元模式(Flyweigh),也叫蝇量模式:运行共享技术有效地支持大量细粒度的对象。针对系统中存在的大量重复对象,享元模式通过减少重复对象创建的数量,来减少内存占用和提高性能。
享元模式的核心是:共享与分离,共享对象中不变的部分,分离对象中可变的部分。享元对象能做到共享的关键是区分内蕴状态和外蕴状态。所谓共享,即多个对象内部的状态应当是一样的,否则就谈不上共享。
内蕴状态是存储在享元对象内部的,并且是不会随环境的改变而有所不同。因此,一个享元可以具有内蕴状态并可以共享。
外蕴状态是随环境的改变而改变的、不可以共享的。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候在传入享元对象内部。外蕴状态不可以影响享元对象的内蕴状态,它们是相互独立的。
二、角色
抽象享元(Flyweight)角色:给出一个抽象接口,以规定出所有具体享元角色需要实现的方法
具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定出的接口。如果有内蕴状态,必须负责为内蕴状态提供存储空间
享元工厂(FlyweightFactory)角色:本负责创建和管理享元角色。当客户端对象调用一个享元对象的时候,享元工厂会检查系统中是否已经有一个符合要求的享元对象。如果已经有,享元工厂就提供这个已有的享元对象;如果没有,享元工厂就创建一个享元对象
三、享元模式
包含抽象享元角色、具体享元角色、享元工厂
1 抽象享元
public interface NaviInfo {
void showNaviInfo(String navitype);
}
2 具体享元
public class ConcreteNaviInfo implements NaviInfo {
/**
* 内蕴状态
*/
private String from, dest;
public ConcreteNaviInfo(String from, String dest) {
this.from = from;
this.dest = dest;
}
/**
* navitype是外蕴状态,不影响内蕴状态
*/
@Override
public void showNaviInfo(String navitype) {
if (navitype.equals("taxi")) {
System.out.println(String.format("%s to %s - an hour - taxi", from, dest));
} else if (navitype.equals("bus")) {
System.out.println(String.format("%s to %s - two hours - bus", from, dest));
}
}
}
3 享元工厂
public class NaviTypeFactory {
private static Map<String, NaviInfo> map = new HashMap<>();
public static NaviInfo getNaviInfo(String from, String dest) {
String key = from + "-" + dest;
if (map.containsKey(key)) {
System.out.println("use cache object");
return map.get(key);
} else {
System.out.println("create new object");
NaviInfo naviInfo = new ConcreteNaviInfo(from, dest);
map.put(key, naviInfo);
return naviInfo;
}
}
}
4 测试
public class Client {
public static void main(String[] args) {
NaviInfo naviInfo1 = NaviTypeFactory.getNaviInfo("A", "B");
naviInfo1.showNaviInfo("taxi");
NaviInfo naviInfo2 = NaviTypeFactory.getNaviInfo("A", "B");
naviInfo2.showNaviInfo("bus");
}
}