设计模式:享元(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) 常常应用于系统底层的开发,以便解决系统的性能 ...
随机推荐
- java多线程开发之CyclicBarrier,CountDownLatch
最近研究了一个别人的源码,其中用到多个线程并行操作一个文件,并且在所有线程全部结束后才进行主线程后面的处理. 其用到java.util.concurrent.CyclicBarrier 这个类. Cy ...
- unity换装系统+网格合并
这里的做法是模型把所有衣服全部穿上作为一个资源 然后还有一个只有骨骼信息的骨架资源 将这2个制作好了Prefab 模型部件数据 资源数据 [代码] using System.Collections; ...
- MySQL的模糊搜索
1.模糊搜索 第一时间我马上想到了关键字 like 1.1.所要查询的字段中包含特定 字符,但不确定其位置,使用两个%包起来 select * from phone where provider li ...
- NMAP - A Stealth Port Scanner--reference
http://nmap.org/bennieston-tutorial/ 实例:nmap -sP 192.168.21.* Contents 1 Introduction Nmap is a fre ...
- java.lang.NumberFormatException: For input string: "1" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang
java.lang.NumberFormatException: For input string: "1" at java.lang.NumberFormatException ...
- [转]vs2012 + web api + OData + EF + MYsql 开发及部署
本文转自:http://www.cnblogs.com/liumang/p/4403436.html 先说下我的情况,b/s开发这块已经很久没有搞了,什么web api .MVC.OData都只是听过 ...
- Linux文件夹和文件创建删除命令
Linux删除文件夹命令 linux删除目录很简单,很多人还是习惯用rmdir,不过一旦目录非空,就陷入深深的苦恼之中,现在使用rm -rf命令即可.直接rm就可以了,不过要加两个参数-rf 即:rm ...
- VS快捷键设置无效
使用Resharper 后发现有些快捷键冲突,但是在工具-选项-键盘 设置后不管用,后来发现有一个移除功能,即移走原来的快捷键; 先选择下拉框1中自己用不到的快捷键,然后移除掉; 备注: 注意观察 快 ...
- Shiro - 关于Realm
之前在Authentication和Authorization中也提到Realm. 无论是身份验证还是权限验证,无论数据以什么方式存在,我们都需要访问一些数据并将其转换为Shiro可以识别的格式. 通 ...
- MongoDB 学习(三)MongoDB 和 Spring 整合(Maven)
一.MongoDB 和 Spring 整合(Maven) 1.相关 jar 包准备 2.用 Maven 创建项目,pom.xml 文件 <project xmlns="http://m ...