享元模式思想与实践

1.享元模式定义

        通过减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式
        其实这句话包含两个含义,一个是每创建一个对象,该对象都会占用内存,与此同时对象的创建是需要消耗时间的。第二个是创建对象的数量是可以减少的,怎么减少呢?通过复用已经创建好的对象,已经创建好的对象能够替换本来打算创建的对象功能,怎么复用呢,通过缓存,把已经创建好的对象放到缓存里,下次需要的时候,直接从缓存里拿,这样不就节省了时间。
          享元模式与其说是一种设计模式,其实更多可以称为是一种计算机的设计思想,它的本质还是基于一个前提:计算机的内存的有限的,建立一些对象有时代价很大。这种设计思想早就在软件领域遍地开花了。比如说数据库连接池,即因建立数据库连接代价较大,为了降低数据库操作的代价,通过建立数据库连接池,提前建立多个数据库连接放到“池子”里,当应用逻辑需要操作数据库时,直接从池子里找一个空间的数据库连接进行操作。

2.享元模式示例

      本文打算从java的字符串常量池来介绍“享元模式”这种思想。
        首先解释一下jvm中容易混淆的三个概念:

  • class文件常量池:

        位于java类文件在编译后会生成.class文件,这个.class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),这是class文件常量池用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。 字面量就是我们所说的常量概念,如文本字符串、被声明为final的常量值等。 符号引用是一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可(它与直接引用区分一下,直接引用一般是指向方法区的本地指针,相对偏移量或是一个能间接定位到目标的句柄)。
       

  • 运行时常量池:

       是class常量池被加载到内存之后的版本。(它同样拥有所有的类)。不同之处是:它的字面量可以动态地添加(String#intern()),符号引用会被解析为直接引用。

  • 字符串常量池

       是一个String Table类,实质上是一个Hash表,默认长度是1009。全局字符串池里的内容是在类加载完成,经过验证,准备阶段之后在堆中生成字符串对象实例存到string pool中。以如下代码为例:

String s1= new String ("test abc"); 
String s2= "test abc";
String s3= "test "+"abc";

        当运行第一行代码时,首先会创建一个字符串常量“test abc”,jvm会从字符串常量池中查看是否存在字符串常量”test abc”,在本例中是没有的,因此,首先在堆中创建”test abc”这个对象,然后在字符串常量池中创建一个直接引用,指向刚才创建的”test abc”对象(桔色文本框所示),接下来,会将”test abc”传递给String的构造函数(new String触发),此时,会在堆中创建一个新的”test abc”,如图中所示,最终栈中的变量s1指向了这个新的”test abc”对象。疑问来了,此时的字符串常量池中的引用以及桔色的”test abc”对象好像并没有用,实际上,这里是为了以后的使用。
        当运行第二行代码时,jvm再次发现要创建字符常量,此时jvm会从字符串常量池中查看是否已经有指向”test abc”的引用,发现已经有了,就把地址返回给变量s2,s2最终也引用了桔色的”test abc”。
        当运行第三行代码时,实际上编译器会做优化,将"test "+“abc"在编译时,替换成"test abc”,因此实际上在运行时,第三行代码与第二代码完全一样,同样从字符串常量池中获取了对象的引用,直接引用桔色的”test abc”,这也是享元模式思想的实践运用。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值