设计模式:享元(FlyWeight)模式
设计模式:享元(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)模式的更多相关文章
- Java 实现享元(Flyweight)模式
/** * 字母 * @author stone * */ public class Letter { private String name; public Letter(String name) ...
- 十二、享元(Flyweight)模式--结构模式(Structural Pattern)
Flyweight在拳击比赛中指最轻量级,即"蝇量级",有些作者翻译为"羽量级".这里使用"享元 模式"更能反映模式的用意. 享元模式以共享 ...
- python 设计模式之享元(Flyweight)模式
#写在前面 这个设计模式理解起来很容易.百度百科上说的有点绕口. #享元模式的定义 运用共享技术来有効地支持大量细粒度对象的复用. 它通过共享已经存在的对橡大幅度减少需要创建的对象数量.避免大量相似类 ...
- 设计模式C++描述----12.享元(Flyweight)模式
一. 概述 在面向对象系统的设计何实现中,创建对象是最为常见的操作. 这里面就有一个问题:如果一个应用程序使用了太多的对象,就会造成很大的存储开销.特别是对于大量轻量级(细粒度)的对象,比如在文档编辑 ...
- 享元(FlyWeight)模式
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式.享元模式尝试 ...
- 十一、结构模式之享元(Flyweight)模式
什么是享元模式 享元模式是对象的结构模式,是运用共享技术来有效的支持大量细粒度的对象.享元对象能做到共享的关键是区分内蕴状态和外蕴状态.一个内蕴状态是存储在享元对象内部,并且是不会随环境改变而有所不同 ...
- 8. 星际争霸之php设计模式--享元模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- C++设计模式——享元模式
本文版权归果冻说所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.如果这篇文章对你有帮助,你可以请我喝杯咖啡. » 本文链接:http:// ...
- 【设计模式】Java设计模式 - 享元模式
Java设计模式 - 享元模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...
- java设计模式——享元模式
一. 定义与类型 定义:提供了减少对象数量从而改善应用所需的对象结构的方式,运用共享技术有效地支持大量细粒度的对象 类型:结构性 二. 使用场景 (1) 常常应用于系统底层的开发,以便解决系统的性能 ...
随机推荐
- 当页面有多个js文件时,应如何引入?
1. 我们知道如果一个页面有多个js文件,并且这些js文件有的还有依赖关系的时候,我们就要特别注意他们之间的引入顺序,否则就会报错. 如:一个js文件依赖jquery,我们就要先引入jquery,然后 ...
- Oracle 中运用rollup和cube实现汇总运算
前言.看了很多的随笔博文内容都是关于rollup和cube的用法,发现一个问题,很多都是一样或者转载的,但这都不是重点,重点是,他们写的都太专业化了,直接给一个结论,并没有给出整个推理出这个结论的过程 ...
- MySQL表级约束和列级约束
对一个数据列建立的约束,称为列级约束 对多个数据列建立的约束,称为表级约束 列级约束即可以在列定义时生命,也可以在列定义后声明. 表级约束只能在列定义后声明. NOT NULL和DEFAULT只存在列 ...
- Jmeter运行badboy录制的脚本
前言 进行性能测试的站点为:在本地搭建的bugfree 一.badboy录制脚本 1.启动bugfree服务 2.打开badboy进行脚本录制 2.1.打开badboy,按下启动录制按钮,在地址栏中输 ...
- hibernate 学习笔记1
Hibernate session1 1.连接池的最小连接数指的是连接池初始化之后,就存在的连接数,这些连接放在内存中,等待被使用.最大连接数限定了连接池中最大同时连接数量,如果超过了这个数量,则进入 ...
- React.js 小书 Lesson25 - 实战分析:评论功能(四)
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson25 转载请注明出处,保留原文链接和作者信息. (本文未审核) 目前为止,第二阶段知识已经基本 ...
- CVE-2017-6920 Drupal远程代码执行漏洞学习
1.背景介绍: CVE-2017-6920是Drupal Core的YAML解析器处理不当所导致的一个远程代码执行漏洞,影响8.x的Drupal Core. Drupal介绍:Drupal 是一个由 ...
- 使用YUM安装MySQL 5.5(适用于CentOS6.2/5.8及Fedora 17/16平台)
目前CentOS/Red Hat (RHEL) 6.2官方自带的mysql版本为5.1,mysql5.5已经出来了. 相比mysql5.1,mysql5.5不仅在多个方面进行了改进: 性能上有了很大提 ...
- [转]NLog 自定义字段 写入 oracle
本文转自:http://www.cnblogs.com/skyapplezhao/p/5690695.html 1.通过Nuget安装NLog 下载,简单入门 请参照 我刚才转的几篇文章,下面我直接贴 ...
- easyui导出当前datagrid数据(Word)
JS代码可参考http://www.cnblogs.com/mu1516633121/p/7753423.html 同样是winform架构下应用到Aspose.Words来读写Word文档 其中Se ...