例子应用:
比如说一个文本系统,每个字母定一个对象,那么大小写字母一共就是52个,那么就要定义52个对象。如果有一个1M的文本,那么字母是何其的多,如果每个字母都定义一个对象那么内存早就爆了。那么如果要是每个字母都共享一个对象,那么就大大节约了资源。
在Java语言中,String类型就是使用了享元模式。String对象是final类型,对象一旦创建就不可改变。在JAVA中字符串常量都是存在常量池中的,JAVA会确保一个字符串常量在常量池中只有一个拷贝。String a="abc",其中"abc"就是一个字符串常量。
数据库连接池,线程池等即是用享元模式的应用。
什么是享元模式
大量细粒度对象共享复用。复用我们内存中已存在的对象,降低系统创建对象实例的性能消耗。
享元模式:“享”就是分享之意,指一物被众人共享,而这也正是该模式的终旨所在。
享元模式有点类似于单例模式,都是只生成一个对象来被共享使用。这里有个问题,那就是对共享对象的修改,为了避免出现这种情况,我们将这些对象的公共部分,或者说是不变化的部分抽取出来形成一个对象。这个对象就可以避免到修改的问题。
主要解决
在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
何时使用
1、系统中有大量对象。
2、这些对象消耗大量内存。
3、需要缓冲池的场景。
4、这些对象的状态大部分可以外部化。
5、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。
6、系统不依赖于这些对象身份,这些对象是不可分辨的。
7、当我们系统中某个对象类型的实例较多的情况,并且要求这些实例进行分类后,发现真正有区别的分类很少的情况。
如何解决
用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。
关键代码
用 HashMap 存储这些对象。
优点
大大减少对象的创建,节约内存空间,降低系统的内存,提高系统的性能。
缺点
提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
享元模式一般是给出本地内存资源节省的一个方案,并不适合互联网上的分布式应用的情况,不过享元模式对于排他性的要求资源的控制,是个不错的选择的。
注意事项:
1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。
2、这些类必须有一个工厂对象加以控制。
内部状态、外部状态。
内部状态:在享元对象内部不随外界环境改变而改变的共享部分。
外部状态:随着环境的改变而改变,不能够共享的状态就是外部状态。
内部状态存储于享元对象内部,而外部状态则应该由客户端来考虑。
享元工厂类
享元模式的核心在于享元工厂类,享元工厂类的作用在于提供一个用于存储享元对象的享元池,用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象。
角色
抽象享元:一个接口或抽象类;
具体享元:内部状态为其成员属性,其实例为享元对象,可以共享;
享元工厂:生产享元对象,将具体享元对象存储在一个享元池中,享元池一般设计为一个存储“键值对”的集合;
客户端:使用享元对象
http://www.cnblogs.com/V1haoge/p/6542449.html
http://blog.csdn.net/jason0539/article/details/22908915
http://www.runoob.com/design-pattern/flyweight-pattern.html
http://www.cnblogs.com/hegezhou_hot/archive/2010/12/12/1903728.html