享元模式通过尽可能的复用已经存在的对象,从而尽量少的创建新对象,以节约系统的内存和提供系统性能。在享元模式中,对象的属性分为两种,内部状态和外部状态。内部状态指的是对象中不随外部变化的属性,属于对象本身的特征属性(比如ID)。外部状态指的是对象中可以随外部变化的属性,可以在外部设置对象的外部状态。
享元模式的思想就是缓存和复用,重点关注的是性能。所以当系统中存在大量的对象,内存开销较大或者对象的大部分的属性是外部状态情况下,可以考虑享元模式。抽象一下,可以通过缓存解决的问题,一般都可以应用享元模式。
2、案例 2.1、背景维秘秀(维多利亚的秘密)是最高等级的秀场,全世界的超模也以能登上维秘秀舞台为傲。对于每一套造型(对象)来说,包含模特(对象的内部状态)和服装(对象的外部状态)。能使用的模特是有限的,但是要展示的服装却要远远超出这个数量,所以在展示每一套服装的时候,需要对模特进行复用。导演要展示一个造型,只需要从目前可用的模特人群(缓存)中喊一个过来,穿上对应的服装,即可走上T台。那么如果目前没有可用的模特怎么办呢?那就招个模特进来,实在不行导演自己上咯。
2.2、实现1)秀接口
public interface Show
{
void show();
}
2) 造型类
public class Model implements Show
{
private String name;
private String style;
public Model(String name)
{
this.name = name;
}
public void setStyle(String style)
{
this.style = style;
}
@Override public void show()
{
System.out.println(name+"展示"+style);
}
}
3)造型工厂,带有缓存池
import java.util.HashMap;
import java.util.Map;
public class ModelFactory
{
private static Map<String, Show> models = new HashMap<String, Show>();
public static Show getShow(String name)
{
Model model = (Model)models.get(name);
if (model == null)
{
model = new Model(name);
models.put(name,model);
}
return model;
}
}
4)验证程序
/**
* 验证
*/
public class Demo
{
public static void main(String[] args)
{
Model model = (Model)ModelFactory.getShow("米兰达·可儿");
model.setStyle("迷幻Bono系列");
model.show();
model = (Model)ModelFactory.getShow("刘雯");
model.setStyle("冰与火系列");
model.show();
model = (Model)ModelFactory.getShow("米兰达·可儿");
model.setStyle("天使肖像系列");
model.show();
}
}
5)运行结果
3、总结米兰达·可儿展示迷幻Bono系列
刘雯展示冰与火系列
米兰达·可儿展示天使肖像系列Process finished with exit code 0
优点:对象复用,降低内存消耗。
缺点:无法做到线程 安全,如果一个线程正在复用,修改其外部状态,而另外一个线程正在进行使用,就会造成问题。