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

package designMode.Flyweight.web2;

import java.util.HashMap;

public class WebSiteFactory {

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

//获得网站分类

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 Strin 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 g getName(){

return name;

}

}

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

package designMode.Flyweight.web2;

public abstract class WebSite {

public abstract void use();

public abstract 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++);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值