写点什么

【源码分析设计模式 7】Integer 中的享元模式

用户头像
极客good
关注
发布于: 刚刚

//获得网站分类


public WebSite getWebSiteCategory(String key) {


if(!pool.containsKey(key)) {


pool.put(key, new ConcreteWebSite(key));


}


return (WebSite)pool.get(key);


}


//获得网站分类总数


public int getWebSiteCount() {


return pool.size();


}


}

4、client 客户端

这里测试用例给了两种网站,原先我们需要做三个产品展示和三个博客的网站,也即需要六个网站类的实例,但其实它们本质上都是一样的代码,可以利用用户 ID 号的不同,来区分不同的用户,具体数据和模板可以不同,但代码核心和数据库却是共享的。


package designMode.Flyweight.web2;


public class Client {


public static void main(String[] args) {


WebSiteFactory factory = new WebSiteFactory();


WebSite fx = factory.getWebSiteCategory("产品展示");


fx.use();


WebSite fy = factory.getWebSiteCategory("产品展示");


fy.use();


WebSite fz = factory.getWebSiteCategory("产品展示");


fz.use();


WebSite fa = factory.getWebSiteCategory("博客");


fa.use();


WebSite fb = factory.getWebSiteCategory("博客");


fb.use();


WebSite fc = factory.getWebSiteCategory("博客");


fc.use();


System.out.println("网站分类总数为:" + factory.getWebSiteCount());


}


}

5、运行结果


可以看出,虽然我们做了 6 个网站,但网站分类只有 2 个。这样基本算是实现了享元模式的共享对象的目的,但想想上面提到的内部状态和外部状态,这里实际上没有体现对象间的不同,只体现了它们的共享部分。

6、用户类

所以我们再加一个用户类,作为网站类的外部状态,并在 use()方法中传递用户对象,UML 如下:



下面添加一个 User 类。


package designMode.Flyweight.web2;


public class User {


private String name;


public User(String name){


this.name = name;


}


public String getName(){


return name;


}


}


然后再对 use()方法进行修改,添加参数,以抽象类为例:


package designMode.Flyweight.web2;


public abstract class WebSite {


public abstract void use();


public abst


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


ract void use(User user);


}


而客户端中只需对每一个网站添加一个用户即可,如:


fx.use(new User("素小暖"));


运行结果如下:



这样就可以协调内部与外部状态,哪怕接手了上千个网站的需求,只要要求相同或类似,实际开发代码也就是分类的哪几种。


七、Integer 的享元模式解析



1、测试类

package designMode.advance.flyWeight;


public class FlyWeight {


public static void main(String[] args) {


//如果 Integer.valueOf(x) x 在 -128 --- 127 直接,就是使用享元模式返回,如果不在


//范围类,则仍然 new


//小结:


//1. 在 valueOf 方法中,先判断值是否在 IntegerCache 中,如果不在,就创建新的 Integer(new), 否则,就直接从 缓存池返回


//2. valueOf 方法,就使用到享元模式


//3. 如果使用 valueOf 方法得到一个 Integer 实例,范围在 -128 - 127 ,执行速度比 new 快


Integer x = 127; // 得到 x 实例,类型 Integer


Integer y = new Integer(127); // 得到 y 实例,类型 Integer


Integer z = Integer.valueOf(127);//..


Integer w = new Integer(127);


System.out.println(x.equals(y)); // 大小,true


System.out.println(x == y ); // false


System.out.println(x == z ); // true


System.out.println(w == x ); // false


System.out.println(w == y ); // false


Integer x1 = Integer.valueOf(200);


Integer x2 = Integer.valueOf(200);


System.out.println("x1==x2" + (x1 == x2)); // false


}


}

2、如果想了解怎么实现共享的,就得分析 Integer 的源代码

Integer x = 127;和 Integer z = Integer.valueOf(127);是一个意思;


下面我们来看下 valueOf 方法:


//意思就是 在一个区间之内,直接用 IntegerCache.cache[]数组里面的数返回,否则 new 一个新对象。


public static Integer valueOf(int i) {


assert IntegerCache.high >= 127;


if (i >= IntegerCache.low && i <= IntegerCache.high)


return IntegerCache.cache[i + (-IntegerCache.low)];


return new Integer(i);


}


再看一下 IntegerCache 类:


//是 Integer 内部的私有静态类,里面的 cache[]就是 jdk 事先缓存的 Integer。


private static class IntegerCache {


static final int low = -128;//区间的最低值


static final int high;//区间的最高值,后面默认赋值为 127,也可以用户手动设置虚拟机参数


static final Integer cache[]; //缓存数组


static {


// high value may be configured by property


int h = 127;


//这里可以在运行时设置虚拟机参数来确定 h :-Djava.lang.Integer.IntegerCache.high=250


String integerCacheHighPropValue =


sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");


if (integerCacheHighPropValue != null) {//用户设置了


int i = parseInt(integerCacheHighPropValue);


i = Math.max(i, 127);//虽然设置了但是还是不能小于 127


// 也不能超过最大值


h = Math.min(i, Integer.MAX_VALUE - (-low) -1);


}


high = h;


cache = new Integer[(high - low) + 1];


int j = low;


//循环将区间的数赋值给 cache[]数组


for(int k = 0; k < cache.length; k++)


cache[k] = new Integer(j++);


}


private IntegerCache() {}


}


其实很简单,就是用一个 Integer 数组先缓存了,后面如果是是在区间内的数直接从缓存数组中取,否则才构造新的 Integer。缓存思想还是很重要的!谢谢大家观看。


八、享元模式和单例模式的区别




用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
【源码分析设计模式 7】Integer中的享元模式