设计模式系列21---避免浪费的享元模型

enter image description here

单例模式垄断了对资源的访问,避免了多次生成带来的重复浪费。
但有时候,我们并没有这么严格的限制,还是希望多几个干活的,或者说
我们的实例有部分的重用功能,但又不能像单例那样只有一个,还是需要很多的实例。

具体如:

我们服务器缓存了100W个用户的信息,但是有一些冗余,例如我们的年龄只有100个取值,最多150是不是!但我们有100个用户,每个都有一个单独的年龄字段,相对是有点多余的,如果可以只压缩到100个的话。或者我们的用户里面的省会信息,也就34个!

好了,废话那么多,到底这个享元应该怎么写呢?

代码实现

我们的用户
public class UserInfo {

    private String uuid;
    private int age;
    private String name;

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

这个就是我们的用户啦,配一个ID,一个年龄,一个名字属性。

接着我们设计一个用户的对象池,他的KEY为年龄。

public class UserInfoPool extends UserInfo {

    private String key;

    public UserInfoPool(String key) {
        this.key = key;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

}

然后我们的工厂,他负责生成用户,保存用户信息。

public class UserInfoFactory {

    private static HashMap<String, UserInfo> pool = new HashMap<String, UserInfo>();

    public static UserInfo getUserInfo(String key) {
        UserInfo result = null;
        if (!pool.containsKey(key)) {
            result = new UserInfoPool(key);
            pool.put(key, result);
        } else {
            System.out.print("从池中获取对象," + key);
            result = pool.get(key);
        }
        return result;
    }    
}

准备好后,我们来看下我们的测试

public class Client {

    public static void main(String[] args) {    
        for (int i = 0; i < 100; i++) {
            String key = "age" + i;
            UserInfoFactory.getUserInfo(key);
        }
        UserInfoFactory.getUserInfo("age" + 92);    
    }
}

类图

enter image description here

后记

享元模型解释器放到最后,因为以前项目没有写过,不熟悉,查看了不少文章和书籍记录资料,都没有那个解释彻底的很明白的,对他的使用也不是很清晰,看到的有淘宝的主题的案例,记事本的文字等。但有些逻辑上的细节并不是很能自圆其说。所以这个一直拖着到这里。
现在的这个案例也不算很好,但暂时先写着,放在这里,那天有新的感觉了,再来更新。

但感觉这个享元在高并发的情况下还是会有用处的,保存一些公共的内容,降低对象的生成,节约内存。

热评文章