享元模式

概念

        运用共享技术有效地支持大量的细粒度的对象(flyweight)。通过对对象的共享(重复使用),避免创建过多对象因为过多的对象将损耗应用的性能,甚至是造成内存泄露。

        共享对象的体系中,也可以有不能共享的子类。

        由于对象是共享的,所以用户不能对对象进行实例化,因此需要建立一个工厂类单独为用户提供共享的对象。

内部状态与外部状态

        对于共享的对象,关键在于将它的属性分为两个部分:内部状态与外部状态。内部状态指的是存储于flyweight中,不随场景的改变而改变;外部状态取决于使用flyweight的场景,并根据场景的变化而变化,不可共享,用户在使用时必须为对象提供外部状态。

        比如要为一篇txt文档中的每一个字符建立一个对象,则对象太多,容易oom,可以采用享元模式。为字符表中的每一个字符建立一个对象(可以认为是字母,如果是汉字的话就算了),这个字符就是该flyweight的内部状态,字符显示的位置就是外部状态。

关键词

        共享——对象重复使用,避免不同的环境下大量创建对象。

使用场景

        必须同时满足下列要求才可以使用享元模式。

        1,系统内部使用了大量的对象,造成了内存的浪费。

        2,剔除对象内部的外部状态后,可以使用较少的对象代替原来大量的对象,即能明显地降低对象的数量。

享元工厂

        由于对象需要重复使用,因此必须提供一个获取对象的工厂类——不能让使用者自己new,因为使用者new的时候并不能保证该对象可以重复使用——这个工厂类就是享元工厂,它负责给客户端返回对象,并将该对象缓存起来。

        比如有一个bean(来源于设计模式之禅),它结构如下:

<span style="font-size:18px;">public class Person {
    private String subject;//科目
    private String code;//准考证号
    private String name;//考生姓名
    private String location;//考试地点
}</span>
        对于科目与考试地点来说,它的数目是有限的。因此科目+考试地点可以组成一个Person对象的可共享部分,可以将这两部分相同的对象进行复用。而name,code等属性需要获取对象之后重新赋值。因此,工厂的示例如下:
<span style="font-size:18px;">    private static Map<String,Person> mPersons = new HashMap<>(); 
    public static Person getPerson(String location,String subject){
        String key = location+"-"+subject;
        if(mPersons.containsKey(key)) {//如果有对象,则使用旧对象
            return mPersons.get(key);
        }else{//如果没有,则new一个
            Person p = new Person();
            p.setLocation(location);
            p.setSubject(subject);
            mPersons.put(key,p);
            return p;
        }
    }</span>

多线程

        在多线程中对同一个对象进行操作,必然会导致对象中数据出现混乱。这也是享元模式一个无法避免的问题,唯一的解决办法就是创建合适多个对象,既能满足多线程的需求,又能不至于因为对象过多而导致内存泄露。

总结

        享元模式实质就是对已使用过的对象的重复利用,它使我们使用到了共享技术,为了方便对这些对象的创建与管理,使用一个工厂类专门用于获取对象(无论这个对象是new出来的,还是从旧有对象中复用的)。

        而对象的复用,可以根据对象中一部分属性(比如上面的location与subject)生成一个key值,该key值就是对象的唯一标识。而有些对象的属性都是不可共享的(如Message),那么根本不需要生成key值,只需要使用List集合将所有的对象存储起来,每一次获取时直接从list中获取即可。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值