揭秘设计模式:享元模式(FlyWeight)的学习与理解(1)

    链接地址:http://www.xx566.com/detail/114.html

    今天学习到了一种设计模式——享元模式(FlyWeight),这里做下总结,早上在群里面交流多线程的时候,提到了关键字volatile,它可以理解 为是轻量级的synchronized,用于锁定基本变量,确保线程同步。volatile关键字修饰的变量,任何对该变量的写操作,都会绕过高速缓存, 直接写入主内存,对该变量的读操作,也是直接读取主内存。然后问题出现了,我们讨论了主内存,讨论了常量池,讨论了自动装箱,讨论了-128到127,又 学习到了一种设计模式,享元模式(FlyWeight)。

    String是final类型的对象,即对象一旦创建就不可改变,我们经常需要理解String str1 = "123"与String str2= new String("123")的区别,在Java中,字符串常量存放在栈区,确切的讲是在栈区的常量池中,而我们使用new关键字则是在堆内存开辟了空间, 创建了一个String对象,这也就是str1==str2返回false的原因,其实是两个对象的地址并不相同,str1引用指向了常量池中的字符串常 量"123",str2引用指向了堆内存的对象。

    栈区有一个很重要的特性:即存在栈中的数据可以共享,如果我们使用String str1 = "123",String str2 = "123",那么我们使用str1==str2就返回了true,即str1和str2两个引用都指向了常量池中的字符串常量"123",这也是Java 中String类型对享元模式的应用,在JDK1.5中引入了自动装箱和自动拆箱的概念,提供了基本数据类型和对象的互相转变,在包装类中,也有部分采用 了享元模式,我们来看下面一部分代码:

package javase.flyweight;
 
/**
 * 享元模式
 * 
 * @Package javase.flyweight
 * @ClassName: FlyWeightTest
 * @author Realfighter
 * @date 2014-8-3 下午02:08:11
 */
public class FlyWeightTest {
 
    public static void main(String[] args) {
        Integer i1 = 127;
        Integer i2 = 127;
        System.out.println(i1 == i2);// true
        i1 = 128;
        i2 = 128;
        /**
         * 翻开源码,我们看到
         *  public static Integer valueOf(int i) {
                final int offset = 128;
                if (i >= -128 && i <= 127) { // must cache 
                    return IntegerCache.cache[i + offset];
                }
                return new Integer(i);
            }
         */
        System.out.println(i1 == i2);// false
        Long a1 = -129l;
        Long a2 = -129l;
        /**
         * 相应的在Long源码里,也有
         *  public static Long valueOf(long l) {
                final int offset = 128;
                if (l >= -128 && l <= 127) { // will cache
                    return LongCache.cache[(int)l + offset];
                }
                return new Long(l);
            }
         */
        System.out.println(a1 == a2);// false
    }
}

    在今天我看到这样的代码时,感觉好诡异,为什么第二个返回是false,翻看了源码和文章后,明白了:Integer包装类在设计时,只有-128到 127之间的值实现了共享,即存放在栈区常量池中,在范围之外的值,JVM会重新创建对象,存放在堆内存中,这也就解释了128和-129不相等的原因 了。

    下面我们开始学习享元模式,首先来了解一下定义:它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导 致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。(参见百度百科)。

    理解起来有些晦涩,其实就是在系统中如果有多个相同的对象,不必每个对实例化一次,只需要共享一个就可以了,感觉有点像单例模式,不过单例模式更特殊,只 实例化一个对象,单例模式更像是享元模式的特殊情况,当然这只是我自己的理解。在Java中,数据库连接池、线程池等都是享元模式的应用。

    整体来说,享元模式是我很陌生的一种模式,我个人认为也是不常使用到的一种模式,一些资料上的讲解也比较书面,不容易理解,只能自己继续摸索了,请期待:揭秘设计模式:享元模式(FlyWeight)的学习与理解(2)

你可能感兴趣的:(java,设计模式,享元模式)