zoukankan      html  css  js  c++  java
  • 设计模式:享元(FlyWeight)模式

    设计模式:享元(FlyWeight)模式

    一、前言

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

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

    二、代码

     文本文件:

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

     1 package zyr.dp.flyweight;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.FileNotFoundException;
     5 import java.io.FileReader;
     6 import java.io.IOException;
     7 
     8 public class BigChar {
     9 
    10     private char charname;
    11     private String frontData;
    12     public BigChar(char charname){
    13         this.charname=charname;
    14         try {
    15             BufferedReader br=new BufferedReader(new FileReader("big"+charname+".txt"));
    16             StringBuffer sb=new StringBuffer();
    17             String line;
    18             while((line=br.readLine())!=null){
    19                 sb.append(line+"
    ");
    20             }
    21             br.close();
    22             frontData=sb.toString();
    23         } catch (FileNotFoundException e) {
    24             e.printStackTrace();
    25         } catch (IOException e) {
    26             // TODO Auto-generated catch block
    27             e.printStackTrace();
    28         }
    29     }
    30     public void print(){
    31         System.out.println(frontData);
    32     }
    33 }
    BigCharFactory 类:
     1 package zyr.dp.flyweight;
     2 
     3 import java.util.HashMap;
     4 
     5 public class BigCharFactory {
     6 
     7     private HashMap pool=new HashMap();
     8     
     9     private static BigCharFactory bigCharFactory=new BigCharFactory();
    10     
    11     private BigCharFactory(){
    12         
    13     }
    14     
    15     public static BigCharFactory getInstance(){
    16         return bigCharFactory;
    17     }
    18     
    19     public synchronized BigChar getBigChar(char name){
    20         BigChar bigchar=(BigChar)pool.get(""+name);
    21         if(bigchar==null){
    22             bigchar=new BigChar(name);
    23             pool.put(""+name, bigchar);
    24         }
    25         return bigchar;
    26     }
    27     public  BigChar getBigCharNotUsed(char name){
    28         return new BigChar(name);
    29     }
    30     
    31 }

     BigString类:

     1 package zyr.dp.flyweight;
     2 
     3 public class BigString {
     4 
     5     private BigChar [] bigchars;
     6     public BigString(String word,boolean isUsed){
     7         if(isUsed == true){
     8             bigchars=new BigChar[word.length()];
     9             BigCharFactory bf=BigCharFactory.getInstance();
    10             for(int i=0;i<word.length();i++){
    11                 bigchars[i]=bf.getBigChar(word.charAt(i));
    12             }
    13         }else{
    14             bigchars=new BigChar[word.length()];
    15             BigCharFactory bf=BigCharFactory.getInstance();
    16             for(int i=0;i<word.length();i++){
    17                 bigchars[i]=bf.getBigCharNotUsed(word.charAt(i));
    18             }
    19         }
    20     }
    21 
    22     public void print(){
    23         for(int i=0;i<bigchars.length;i++){
    24             bigchars[i].print();
    25         }
    26     }
    27 }

     Main类:

     1 package zyr.dp.flyweight;
     2 
     3 public class Main {
     4 
     5     public static void main(String[] args) {
     6         String name="221100";
     7         testMemory( name, false);
     8         testMemory( name, true);
     9     }
    10     public static void testMemory(String name,boolean isUsed){
    11         System.out.println("是否使用轻量级:"+isUsed);
    12         BigString bs=new BigString(name,isUsed);
    13         bs.print();
    14         countMemory();
    15         System.out.println("=================");
    16     }
    17     public static void countMemory(){
    18         Runtime.getRuntime().gc();
    19         System.out.println("已使用内存:"+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()));
    20     }
    21 }

    运行结果:

    是否使用轻量级:false
    ---****------
    -------*-----
    --------*----
    -----**------
    ----*--------
    --*******----
    
    ---****------
    -------*-----
    --------*----
    -----**------
    ----*--------
    --*******----
    
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    
    ----*****----
    ---*-----*---
    --*-------*--
    --*-------*--
    ---*-----*---
    ----*****----
    
    ----*****----
    ---*-----*---
    --*-------*--
    --*-------*--
    ---*-----*---
    ----*****----
    
    已使用内存:879440
    =================
    是否使用轻量级:true
    ---****------
    -------*-----
    --------*----
    -----**------
    ----*--------
    --*******----
    
    ---****------
    -------*-----
    --------*----
    -----**------
    ----*--------
    --*******----
    
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    -----**-----
    
    ----*****----
    ---*-----*---
    --*-------*--
    --*-------*--
    ---*-----*---
    ----*****----
    
    ----*****----
    ---*-----*---
    --*-------*--
    --*-------*--
    ---*-----*---
    ----*****----
    
    已使用内存:876928
    =================
    运行结果

    三、总结

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

      程序代码

  • 相关阅读:
    追踪神秘的成都Uber:月入2万元是现实还是传说
    打造自己博客(wordpress)的wap手机版本
    今天刚申请成为Uber司机 已经接了5单了....大家有什么想问的吗?
    UBER司机奖励政策
    原生应用native、Web应用、混合应用hybrid:3者的优缺点解析
    “基数排序”之数组中缺失的数字
    html5 新增语义标签
    如何判断Javascript对象是否存在
    HTML 5 <details> 标签
    html5 notifications通知
  • 原文地址:https://www.cnblogs.com/zyrblog/p/9250726.html
Copyright © 2011-2022 走看看