浅谈FlyWeight享元模式

1、前言java

享元(FlyWeight)模式顾名思义,便是轻量级,缘由就是享元,共享元素,这里的元素指的是对象。如何共享对象,那就是在检测对象产生的时候,若是产生的是同一个对象,那么直接使用已经产生的,听起来很像单例模式,其实享元模式的内部实现就是很相似与单例模式的懒汉模式。享元的好处就是,在某些场景下能够节省内存,从而使得程序的性能获得提高。设计模式

那么到底什么对象能够共享呢?好比操做系统安装的时候就已经自动保存的图标、字体等等,这些东西是能够共享的,咱们能够拿来直接使用,好比说Word上面的字体,这些都是享元,由于不会发生改变,属于intrinsic(固定的、内在的、本质的),而有的对象是不能共享的,被称为extrinsic(外在的),本例之中本身使用txt文档建立几个字体,分别表示0,1,2...而后使用程序读取这些字体生成一个对象,这样的对象不能改变,所以能够用来共享。学过计算机高级结构的都知道,共享的内存必定要保证一致性,发生改变的时候也同步更新,而这里的享元从始至终没有发生过改变,所以能够做为共享变量。数组

2、代码多线程

 BigChar类:(单个字符所表达的类)app

package zyr.dp.flyweight;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class BigChar {

    private char charname;
    private String frontData;
    public BigChar(char charname){
        this.charname=charname;
        try {
            BufferedReader br=new BufferedReader(new FileReader("big"+charname+".txt"));
            StringBuffer sb=new StringBuffer();
            String line;
            while((line=br.readLine())!=null){
                sb.append(line+"\n");
            }
            br.close();
            frontData=sb.toString();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public void print(){
        System.out.println(frontData);
    }
}
package zyr.dp.flyweight;

import java.util.HashMap;

public class BigCharFactory {

    private HashMap pool=new HashMap();
    
    private static BigCharFactory bigCharFactory=new BigCharFactory();
    
    private BigCharFactory(){
        
    }
    
    public static BigCharFactory getInstance(){
        return bigCharFactory;
    }
    
    public synchronized BigChar getBigChar(char name){
        BigChar bigchar=(BigChar)pool.get(""+name);
        if(bigchar==null){
            bigchar=new BigChar(name);
            pool.put(""+name, bigchar);
        }
        return bigchar;
    }
    public  BigChar getBigCharNotUsed(char name){
        return new BigChar(name);
    }
    
}
package zyr.dp.flyweight;

public class BigString {

    private BigChar [] bigchars;
    public BigString(String word,boolean isUsed){
        if(isUsed == true){
            bigchars=new BigChar[word.length()];
            BigCharFactory bf=BigCharFactory.getInstance();
            for(int i=0;i<word.length();i++){
                bigchars[i]=bf.getBigChar(word.charAt(i));
            }
        }else{
            bigchars=new BigChar[word.length()];
            BigCharFactory bf=BigCharFactory.getInstance();
            for(int i=0;i<word.length();i++){
                bigchars[i]=bf.getBigCharNotUsed(word.charAt(i));
            }
        }
    }

    public void print(){
        for(int i=0;i<bigchars.length;i++){
            bigchars[i].print();
        }
    }
}
package zyr.dp.flyweight;

public class Main {

    public static void main(String[] args) {
        String name="221100";
        testMemory( name, false);
        testMemory( name, true);
    }
    public static void testMemory(String name,boolean isUsed){
        System.out.println("是否使用轻量级:"+isUsed);
        BigString bs=new BigString(name,isUsed);
        bs.print();
        countMemory();
        System.out.println("=================");
    }
    public static void countMemory(){
        Runtime.getRuntime().gc();
        System.out.println("已使用内存:"+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()));
    }
}

运行结果: 性能

是否使用轻量级:false
---****------
-------*-----
--------*----
-----**------
----*--------
--*******----

---****------
-------*-----
--------*----
-----**------
----*--------
--*******----

-----**-----
-----**-----
-----**-----
-----**-----
-----**-----
-----**-----

-----**-----
-----**-----
-----**-----
-----**-----
-----**-----
-----**-----

----*****----
---*-----*---
--*-------*--
--*-------*--
---*-----*---
----*****----

----*****----
---*-----*---
--*-------*--
--*-------*--
---*-----*---
----*****----

已使用内存:879440
=================
是否使用轻量级:true
---****------
-------*-----
--------*----
-----**------
----*--------
--*******----

---****------
-------*-----
--------*----
-----**------
----*--------
--*******----

-----**-----
-----**-----
-----**-----
-----**-----
-----**-----
-----**-----

-----**-----
-----**-----
-----**-----
-----**-----
-----**-----
-----**-----

----*****----
---*-----*---
--*-------*--
--*-------*--
---*-----*---
----*****----

----*****----
---*-----*---
--*-------*--
--*-------*--
---*-----*---
----*****----

已使用内存:876928
=================

运行结果

3、总结字体

在咱们的程序中,使用了单例模式,同时为了享元,咱们使用了相似于单例模式中的懒汉模式。加入synchronized是为了防止多线程中出现误入,固然在本例中是没有多线程的,加不加锁无所谓。同时,咱们对比了没有使用享元的例子,(对比以前先启动一次GC回收一次内存)能够返现所占用的内存空间,明显使用了享元的占用的内存小,而没有使用享元的占用内存多。而且这里咱们要注意垃圾回收机制,在工厂类中,使用了hashmap来将bigchar对象保存起来,这样就造成了一个DAC(有向无环图),只要pool变量不被释放,咱们使用的共享单元是不会被释放的。这样就保证了bigchar对象数组不被释放,在使用享元模式的时候必定要特别注意这种状况,由于垃圾回收器GC在内存占用过多的时候被唤醒,而后清理那些被使用的内存,采用的方式就是DAC。this

 

浅谈设计模式<最通俗易懂的讲解>spa

相关文章
相关标签/搜索