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

一、前言

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

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

二、代码

 文本文件:

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

 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);
}
}
BigCharFactory 类:
 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);
} }

 BigString类:

 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();
}
}
}

 Main类:

 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
=================

运行结果

三、总结

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

  程序代码

设计模式:享元(FlyWeight)模式的更多相关文章

  1. Java 实现享元(Flyweight)模式

    /** * 字母 * @author stone * */ public class Letter { private String name; public Letter(String name) ...

  2. 十二、享元(Flyweight)模式--结构模式(Structural Pattern)

    Flyweight在拳击比赛中指最轻量级,即"蝇量级",有些作者翻译为"羽量级".这里使用"享元 模式"更能反映模式的用意. 享元模式以共享 ...

  3. python 设计模式之享元(Flyweight)模式

    #写在前面 这个设计模式理解起来很容易.百度百科上说的有点绕口. #享元模式的定义 运用共享技术来有効地支持大量细粒度对象的复用. 它通过共享已经存在的对橡大幅度减少需要创建的对象数量.避免大量相似类 ...

  4. 设计模式C++描述----12.享元(Flyweight)模式

    一. 概述 在面向对象系统的设计何实现中,创建对象是最为常见的操作. 这里面就有一个问题:如果一个应用程序使用了太多的对象,就会造成很大的存储开销.特别是对于大量轻量级(细粒度)的对象,比如在文档编辑 ...

  5. 享元(FlyWeight)模式

    享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式.享元模式尝试 ...

  6. 十一、结构模式之享元(Flyweight)模式

    什么是享元模式 享元模式是对象的结构模式,是运用共享技术来有效的支持大量细粒度的对象.享元对象能做到共享的关键是区分内蕴状态和外蕴状态.一个内蕴状态是存储在享元对象内部,并且是不会随环境改变而有所不同 ...

  7. 8. 星际争霸之php设计模式--享元模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  8. C++设计模式——享元模式

    本文版权归果冻说所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.如果这篇文章对你有帮助,你可以请我喝杯咖啡. » 本文链接:http:// ...

  9. 【设计模式】Java设计模式 - 享元模式

    Java设计模式 - 享元模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...

  10. java设计模式——享元模式

    一. 定义与类型 定义:提供了减少对象数量从而改善应用所需的对象结构的方式,运用共享技术有效地支持大量细粒度的对象 类型:结构性 二. 使用场景 (1)  常常应用于系统底层的开发,以便解决系统的性能 ...

随机推荐

  1. 设置MySQL字符集utf8

    1.修改mysql 配置文件my.cnf 标签[mysqld]下添加即可 character-set-server = utf8 2.创建数据库时设置字符集 create database db_na ...

  2. 2014年北京网络赛 Instrusive HDU 5040 题解 优先队列

    网赛的时候看了这道题,发现就是平常的那种基础搜索题. 由于加了一个特殊条件:可以一次消耗3秒或原地停留1秒. 那就不能使用简单的队列了,需要使用优先队列才行. 题意 告诉一副地图:一个起点,一个终点, ...

  3. Spring Service、Dao进行Junit单元测试

    pring对Controller.Service.Dao进行Junit单元测试总结 ​ 所有用Junit进行单元测试,都需要下面的配置 @RunWith(SpringJUnit4ClassRunner ...

  4. c#,利用WPF的ScaleTransform和TranslateTransform实现图片的缩放效果

    一.缩放要求 1.缩放对象在可视区域内,已对象的中心点进行缩放. 2.缩放对象比可视区大,并且对象各边界都在可视区外围,那么已鼠标位置进行缩放. 3.缩放对象比可视区大,但是缩放后某一边界在可视区的对 ...

  5. CVE-2017-6920 Drupal远程代码执行漏洞学习

     1.背景介绍: CVE-2017-6920是Drupal Core的YAML解析器处理不当所导致的一个远程代码执行漏洞,影响8.x的Drupal Core. Drupal介绍:Drupal 是一个由 ...

  6. .net托管资源与非托管资源

    在项目当中用到的资源分为托管资源和非托管资源,托管资源无非就是什么int.string.datatime之类,托管资源不需要人为去管理,.net framework中有专门针对托管资源的管理机制(GC ...

  7. git提交空文件夹和删除远程文件

    git提交空文件夹 在文件夹中创建 .gitkeep 文件,文件内容如下 # Ignore everything in this directory * # Except this file !.gi ...

  8. 译:Java局部变量类型推断(Var类型)的26条细则

    原文链接:https://dzone.com/articles/var-work-in-progress 作者:Anghel Leonard 译者:沈歌 Java局部变量类型推断(LVTI),简称va ...

  9. Android的消息机制简单总结

    参考文章: http://gityuan.com/2015/12/26/handler-message-framework/#next 参考资料: Android Framework的源码: Mess ...

  10. Linux服务器安装tomcat、JDK、SVN等常用开发软件总结

    本来本文发布到首页的,该网站运营人员移除了,说我这篇博文太简单了,如果感觉我这篇博文有用的,大家给个推荐,打一下运营人员的脸 目录 一.Ubuntu 16.04下安装JDK(spring 3.2不支持 ...