设计模式:享元(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) 常常应用于系统底层的开发,以便解决系统的性能 ...
随机推荐
- 设置MySQL字符集utf8
1.修改mysql 配置文件my.cnf 标签[mysqld]下添加即可 character-set-server = utf8 2.创建数据库时设置字符集 create database db_na ...
- 2014年北京网络赛 Instrusive HDU 5040 题解 优先队列
网赛的时候看了这道题,发现就是平常的那种基础搜索题. 由于加了一个特殊条件:可以一次消耗3秒或原地停留1秒. 那就不能使用简单的队列了,需要使用优先队列才行. 题意 告诉一副地图:一个起点,一个终点, ...
- Spring Service、Dao进行Junit单元测试
pring对Controller.Service.Dao进行Junit单元测试总结 所有用Junit进行单元测试,都需要下面的配置 @RunWith(SpringJUnit4ClassRunner ...
- c#,利用WPF的ScaleTransform和TranslateTransform实现图片的缩放效果
一.缩放要求 1.缩放对象在可视区域内,已对象的中心点进行缩放. 2.缩放对象比可视区大,并且对象各边界都在可视区外围,那么已鼠标位置进行缩放. 3.缩放对象比可视区大,但是缩放后某一边界在可视区的对 ...
- CVE-2017-6920 Drupal远程代码执行漏洞学习
1.背景介绍: CVE-2017-6920是Drupal Core的YAML解析器处理不当所导致的一个远程代码执行漏洞,影响8.x的Drupal Core. Drupal介绍:Drupal 是一个由 ...
- .net托管资源与非托管资源
在项目当中用到的资源分为托管资源和非托管资源,托管资源无非就是什么int.string.datatime之类,托管资源不需要人为去管理,.net framework中有专门针对托管资源的管理机制(GC ...
- git提交空文件夹和删除远程文件
git提交空文件夹 在文件夹中创建 .gitkeep 文件,文件内容如下 # Ignore everything in this directory * # Except this file !.gi ...
- 译:Java局部变量类型推断(Var类型)的26条细则
原文链接:https://dzone.com/articles/var-work-in-progress 作者:Anghel Leonard 译者:沈歌 Java局部变量类型推断(LVTI),简称va ...
- Android的消息机制简单总结
参考文章: http://gityuan.com/2015/12/26/handler-message-framework/#next 参考资料: Android Framework的源码: Mess ...
- Linux服务器安装tomcat、JDK、SVN等常用开发软件总结
本来本文发布到首页的,该网站运营人员移除了,说我这篇博文太简单了,如果感觉我这篇博文有用的,大家给个推荐,打一下运营人员的脸 目录 一.Ubuntu 16.04下安装JDK(spring 3.2不支持 ...