享元模式(FlyWeight Pattern)及其在java自动拆箱、自动装箱中的运用
本文主要从三个方面着手,第一:简要介绍享元模式。第二:享元模式在基本类型封装类中的运用以Integer为例进行阐述。第三:根据第一、第二的介绍,进而推出java是如何实现自动拆箱与装箱的。
第一:简要介绍享元模式。
享元模式的角色:抽象享元类(FlyWeight)、具体享元类(ConcreteFlyWeight)、享元工厂类(FlyWeightFactory)、客户类(Client,相当于一个测试类)
至于FlyWeight pattern如果直接翻译应译为: 蝇量级模式。从蝇量级我们可以知道共享的对象是非常小的。在Integer中共享的数字范围为[-128,127]。老外是不是从共享的对象太小的角度,所以称它为FlyWeight Pattern呢?。
我国人是从FlyWeight Pattern的用途(FlyWeight Pattern 的用途就是共享对象。元,也就是最小的意思。享元就是共享最小对象。)上进行翻译的。
下面给出各个角色的代码:
FlyWeight的代码如下:
package com.qls.flyWeight2;
public interface FlyWeight {
//以外蕴状态【external state】为参数的商业方法。这里假设外蕴状态是String类型的。
void operation(String externalState);
}
ConcreteFlyWeight的代码如下:
package com.qls.flyWeight2;
public class ConcreteFlyWeight implements FlyWeight {
//内蕴状态的私有字段[internal state]
private Character internalState;
//构造一个以内蕴状态为参数的构造方法
public ConcreteFlyWeight(Character internalState) {
this.internalState = internalState;
}
@Override
public void operation(String externalState) {
// TODO Auto-generated method stub
System.out.println("internalState="+internalState+" externalState="+externalState);
}
}
FlyWeightFactory的代码如下:
package com.qls.flyWeight2; import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry; public class FlyWeightFactory {
Map<Character,FlyWeight> files=new HashMap<Character,FlyWeight>();
//构造方法
public FlyWeightFactory() {
// TODO Auto-generated constructor stub
}
//写一个以内蕴状态的工厂方法,以生产FlyWeight对象。
public FlyWeight factory(Character internalState){
if(files.containsKey(internalState)){
return files.get(internalState);
}else{
FlyWeight flyWeight = new ConcreteFlyWeight(internalState);
//把对象保存到Map集合中。
files.put(internalState, flyWeight);
return flyWeight;
}
}
public void checkFlyWeight(){
//打印出FlyWeight对象,以及享元对象。
for(Entry<Character, FlyWeight> en:files.entrySet()){
System.out.println(en.getKey()+"="+en.getValue());
}
}
}
Client的代码如下:
package com.qls.flyWeight2;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建一个享元工厂对象
FlyWeightFactory flyWeightFactory = new FlyWeightFactory();
//向享元工厂对象请求一个内蕴状态为'a'的享元对象
FlyWeight factory = flyWeightFactory.factory(new Character('a'));
//以参量方式传入一个外蕴状态。
factory.operation("ouyangfeng");
//向享元工厂对象请求一个内蕴状态为'b'的享元对象
FlyWeight factory2 = flyWeightFactory.factory(new Character('b'));
//以参量方式传入一个外蕴状态。
factory.operation("sixi");
//向享元工厂对象请求一个内蕴状态为'a'的享元对象
FlyWeight factory3 = flyWeightFactory.factory(new Character('a'));
//以参量方式传入一个外蕴状态。
factory.operation("wallow");
System.out.println(factory==factory3);//返回结果为true。由此可以确定'a'确实做到了享元(共享元数据)
/**
* 打印出享元对象。以及内蕴状态。目的是证明对相同的内蕴状态只创建一个对象。
* 下面语句的输出结果是:
* b=com.qls.flyWeight2.ConcreteFlyWeight@21780f30
a=com.qls.flyWeight2.ConcreteFlyWeight@512d297a
这个输出结果证明了:factory==factory3.
*/
flyWeightFactory.checkFlyWeight();
}
}
第二:享元模式在基本类型封装类中的运用以Integer为例进行阐述。
首先概述一下:在Integer类中享元对象是保存在一个IntegerCache.cache[]这个数组里面的这个数组存放的内容是:[-128,127]之间的数字,这个范围中的Integer,对象只创建一次。
所以你要测验:Integer a=-128; Integer b=-128 ; System.out.println(a==b);输出结果为true. 而Integer c=-129; Integer b=-129 ; System.out.println(a==b);输出结果为false.
要想说清楚这个问题只需看一看private static class IntegerCache 、 public static Integer valueOf(int i)、 public int intValue() 这三个类的源码即可。
private static class IntegerCache的源码如下:(注:在这个源码中我添加了,对这个源码的一些解释)
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
//静态代码块保证了,Integer cache[]在IntegerCache加载时就会被赋值。赋值的结果见第22行
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);//这个循环语句等价于Integer[] cache={new Integer(-128),new Integer(-127),new Integer(-126).........new Integer(126),new Integer(127)}共127+128+1=256个数字。
}//当我们在Integer a=f;直接从这个cache[]数组中进行搜索如果f在[-128,127]之间(例如Integer a=1)不需要new Integer(1)了,而是在这个cache[]数组中等于1的值直接赋值。反之如果 f不在[-128,127]之间则会new Integer(f);这个源代码见下面的valueOf
//即可豁然开朗。同时这也体现了享元模式的运用。在享元模式示例中用HashMap存放对象,对同一个对象只创建一次。这里用的是数组存放对象,对同一个对象也只创建一次。
private IntegerCache() {}
}
valueOf的源代码如下:
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);
}
public static Integer valueOf(int i)这个方法用于把int转换为Integer,它是编译器用于自动装箱的核心方法。由编译器根据代码的实际情况,决定是否调用这个方法。一句话在把int变为Integer时,编译器会自动调用这个方法。
intValue()的源代码如下:
public int intValue() {
return value;
}
public int intValue()这个方法用于把Integer转换为int的。
,它是编译器用于自动拆箱的核心方法。由编译器根据代码的实际情况,决定是否调用这个方法。一句话在把Integer变为int时,编译器会自动调用这个方法。
下面这个例子说明在一下三种情况编译器是如何工作的:三种情况是:int 与Integer Integer与Integer int 与int
package com.qls.gateway;
public class Test6 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int g=1;
int a=1;
int f=189;
//b与c在[-128,127]这个范围内。
Integer b=1;
Integer c=1;
//d和e不在[-128,-127]这个范围内。
Integer d=189;
Integer e=189;
System.out.println(a==g);//true【这个是int 与int的比较】
/**
* 从这两个输出语句System.out.println(f==d);
System.out.println(a==b);得出一个结论当int 与Integer比较时,编译器会把Integer自动拆箱。
证明如下:假设当int 与Integer比较时,编译器会把int自动装箱。那么int f=189.自动装箱过后变为
new Integer(189)相当于用创建了一个对象所以与Integer d=189。不可能是同一个对象,那么f==d也就为
false了,但是输出结果为true。所以假设不成立。
所以当int 与Integer比较时,编译器会把Integer自动拆箱。
*/
System.out.println(f==d);
System.out.println(a==b);
/**
* Integer与Integer比较时:只需看Integer的范围是否在[-128,127]如果在直接从cache[]数组中取,
* 则必然是同一个对象,反之如果不在,则会创建一个对象。
*/
System.out.println(d==e);//输出false
System.out.println(b==c);//输出true.
}
}
享元模式(FlyWeight Pattern)及其在java自动拆箱、自动装箱中的运用的更多相关文章
- Java享元模式(Flyweight Pattern)
享元模式(Flyweight Pattern)主要用于减少创建的对象数量,并减少内存占用并提高性能. 这种类型的设计模式属于结构模式,因为该模式提供了减少对象计数的方法,从而改善应用的对象结构. 享元 ...
- 设计模式系列之享元模式(Flyweight Pattern)——实现对象的复用
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- 二十四种设计模式:享元模式(Flyweight Pattern)
享元模式(Flyweight Pattern) 介绍运用共享技术有效地支持大量细粒度的对象. 示例有一个Message实体类,某些对象对它的操作有Insert()和Get()方法,现在要运用共享技术支 ...
- 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern)
原文:乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) 作者:weba ...
- 设计模式-11享元模式(Flyweight Pattern)
1.模式动机 在面向对象程序设计过程中,有时会面临要创建大量相同或相似对象实例的问题.创建那么多的对象将会耗费很多的系统资源,它是系统性能提高的一个瓶颈. 享元模式就是把相同或相似对象的公共部分提取出 ...
- 七个结构模式之享元模式(Flyweight Pattern)
定义: 运用共享技术对大量细粒度对象的复用,这要求这些对象都很相似,状态变化很小.将这些对象的内部状态和外部状态进行区分,对于内部状态相同的只存储一个对象,而对不同的外部状态则采用不同的操作. 结构图 ...
- 享元模式(Flyweight Pattern)
定义: 采用一个共享来避免大量拥有相同内容对象的开销.这种开销中最常见.直观的就是内存的损耗.享元模式以共享的方式高效的支持大量的细粒度对象. 享元的英文是flyweight,是一个来自体育方面的专业 ...
- 享元模式<Flyweight Pattern>
1.What-是什么? 享元模式是一种轻量级的结构型模式.旨在以共享的方式高效的支持大量的细粒度对象的复用.要求能够共享的对象必须是细粒度对象,这些对象比较相似,状态变化小. 2.Why-为什么? ...
- 【UE4 设计模式】享元模式 Flyweight Pattern
概述 描述 运用共享技术有效地支持大量细粒度对象的复用.系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用. 由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻 ...
- 12.享元模式(Flyweight Pattern)
using System; using System.Collections; namespace ConsoleApplication5 { class Program { /// <summ ...
随机推荐
- 1016-01-首页16-计算配图的frame----MJExtention的使用
-------HWPhoto.h--------------------------------------------- #import <Foundation/Foundation.h> ...
- P2567 [SCOI2010]幸运数字 DFS+容斥定理
P2567 [SCOI2010]幸运数字 题目描述 在中国,很多人都把6和8视为是幸运数字!lxhgww也这样认为,于是他定义自己的“幸运号码”是十进制表示中只包含数字6和8的那些号码,比如68,66 ...
- ABAP 7.51 構文書き方変換について
便利になったなぁと感じたコマンドのメモです.NetWeaver7.40 SP2から使えます. SAP NetWeaver AS for ABAP 7.51 Innovation Package – O ...
- Echarts 解决饼图文字过长重叠的问题
之前在网上查找了很多关于解决饼图文字描述过长导致重叠的问题,找了很多一直没有一个合适的解决方案,最后自己只能花时间研究echarts文档,功夫不负有心人,终于解决了文字重叠展示不全等问题. 废话不多说 ...
- Sqlite客户端的使用
打开一个数据库sqlite3 ${databaseName} 查看当前打开的数据库.database 查看当前打开的数据库中的表.table 查看指定表结构(实际输出是建表语句).schema ${t ...
- TouTiao开源项目 分析笔记12 从总体到局部 构建视频主页面
1.构建视频主列表的整体碎片VideoTabLayout 1.1.首先创建一个VideoTabLayout package com.jasonjan.headnews.module.video; im ...
- 运行SparkStreaming程序时出现 Exception in thread "main" java.lang.NoSuchMethodError: scala.Predef$.ArrowA异常
Exception in thread "main" java.lang.NoSuchMethodError: scala.Predef$.ArrowA 这个问题是版本不统一导致的 ...
- CSS 一些基础知识(优先级、行内元素的一些属性、font-size单位) 怎样不加载图片
CSS大小写不敏感 选择器优先级如下所示: 在属性后面使用 !important 会覆盖页面内任何位置定义的元素样式. 作为style属性写在元素内的样式 id选择器 类选择器 标签选择器 通配符选择 ...
- .net面试那些事
2014-3-30这天从昆明来到了江苏无锡,一周时间,不同地方不同感触. 在经过长达35小时的火车,在上海南见到了我弟,在经过两小时汽车到了无锡.回想起来....在坐汽车途中,虽然自己已很累,但从上海 ...
- 能加载文件或程序集 HRESULT:0x80070057 (E_INVALIDARG)的异常的解决方案
今天下午由于机器蓝屏后,导致我的VS不能够调试我的网站了. 症状就是 : VS无法调试,但是可以编译和发布.而且只是 我在调试时蓝屏的那个项目 不能调试. 出现的错误就是: 能加载文件或程序集“Eny ...