《设计模式之禅》-享元模式的性能平衡

需要下载demo 

demo: https://gitee.com/minstrel01/Design-Pattern-demo.git flyweight_pattern

在报考系统中,我们完全可以重新建立一个类作为外部状态,这样才完全符合面向对象编程的理念

//外部类
public class ExtrinsicState {
    //考试科目
    private String subject;
    //考试地点
    private String location;

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    @Override
    public boolean equals(Object object){
        if (object instanceof ExtrinsicState){
            ExtrinsicState state = (ExtrinsicState) object;
            return state.getLocation().equals(location) && state.getSubject().equals(subject);
        }
        return false;
    }

    @Override
    public int hashCode(){
        return subject.hashCode() + location.hashCode();
    }
}

注意 一定要覆写equals方法和hashcode方法,否则它作为HashMap中的key值时根本没有意义的,只有hashCode值相等,并且equals返回结果为true,两个对象才相等,也只有在这种情况下,才有可能从对象池中查找获得对象

如果把一个对象作为Map类的键值,一定要确保重写了equals方法和hashCode方法,否则会出现通过键值搜索失败的情况,例如map.get(object)等方法

//使用外部类的享元工厂
public class SignInfoFactory2 {
    //池容器
    private static HashMap pool = new HashMap<>();

    //从池中获得对象
    public static SignInfo getSignInfo(ExtrinsicState key){
        //设置返回对象
        SignInfo result = null;
        //池中没有该对象,则建立,并放入池中
        if (!pool.containsKey(key)){
            result = new SignInfo();
            pool.put(key,result);
        }else {
            result = pool.get(key);
        }
        return result;
    }
}

 

public class Client {
    public static void main(String[] args) {
        //使用外部类作为外部状态
        ExtrinsicState state1 = new ExtrinsicState();
        state1.setLocation("上海");
        state1.setSubject("科目1");
        SignInfoFactory2.getSignInfo(state1);
        ExtrinsicState state2 = new ExtrinsicState();
        state2.setLocation("上海");
        state2.setSubject("科目2");
        long currentTime = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            SignInfoFactory2.getSignInfo(state2);
        }
        long tailTime = System.currentTimeMillis();
        System.out.println("使用时间为"+ (tailTime - currentTime) +"ms");

        //以String类型作为外部状态
        String key1 = "科目1上海";
        String key2 = "科目2上海";
        //初始化对象池
        SignInfoFactory.getSignInfo(key1);
        long currentTime1 = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            SignInfoFactory.getSignInfo(key2);
        }
        long tailTime1 = System.currentTimeMillis();
        System.out.println("使用时间为"+ (tailTime1 - currentTime1) +"ms");
    }
}

结果如下

 

使用外部类的效率总是低于使用String的,所以如果使用自己编写的类作为类的外部状态,必须覆写equals方法和hashCode方法,而且执行效率还比较低,这种吃力不讨好的事最好别做,外部状态最好以java的基本类型作为标示 如String,或者 int等,可以大幅度提升效率

 

你可能感兴趣的:(设计模式)