设计模式:享元(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+"\n");
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。

原文地址:https://www.cnblogs.com/zyrblog/p/9250726.html

时间: 2024-10-10 20:38:12

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

Java 实现享元(Flyweight)模式

/** * 字母 * @author stone * */ public class Letter { private String name; public Letter(String name) { this.name = name; } public String getName() { return name; } } /** * 一个产生字母对象的 享元工厂(单例工厂) * @author stone * */ public class LetterFactory { private

设计模式——享元模式

Flyweight 直译为蝇量.就其表示的模式来说,翻译成享元,确实是不错的 package designpattern.structure.flyweight; public interface Flyweight { void action(int arg); } package designpattern.structure.flyweight; public class FlyweightImpl implements Flyweight { public void action(int

设计模式——享元模式详解

0. 前言 写在最前面,本人的设计模式类博文,建议先看博文前半部分的理论介绍,再看后半部分的实例分析,最后再返回来复习一遍理论介绍,这时候你就会发现我在重点处标红的用心,对于帮助你理解设计模式有奇效哦~本文原创,转载请注明出处为SEU_Calvin的博客. 春运买火车票是一件疯狂的事情,同一时刻会有大量的查票请求涌向服务器,服务器必须做出应答来满足我们的购票需求.试想,这些请求包含着大量的重复,比如从A地到B地的车票情况,如果每次都重复创建一个车票查询结果的对象,那么GC任务将非常繁重,影响性能

小菜学设计模式——享元模式

背景 如果一个应用程序中使用了大量的对象,而大量的这些对象造成了恨得的存储开销时就应该考虑这个新是设计模式:享元模式. 1.使用意图 最大限度地减少了尽可能与其他类似的对象多的数据共享内存的使用,换句话说就是通过共享对象达到系统内维护的对象数量减少从而降低了系统的开销.因为是细粒度的控制,所以享元模式不是控制整个实例共享,那为何不用单例呢?而是只是共享对象的部分,不共享的部分称为对象的外部状态,需要外部动态修改这个共享对象. 2.生活实例 围棋的棋子,如果用编程去实现的话,势必要new出很多实例

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

题记==============================================================================本php设计模式专辑来源于博客(jymoz.com),现在已经访问不了了,这一系列文章是我找了很久才找到完整的,感谢作者jymoz的辛苦付出哦! 本文地址:http://www.cnblogs.com/davidhhuan/p/4248186.html============================================

[工作中的设计模式]享元模式模式FlyWeight

一.模式解析 Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意.享元模式是对象的结构模式.享元模式以共享的方式高效地支持大量的细粒度对象. 享元模式:主要为了在创建对象时,对共有对象以缓存的方式进行保存,对外部对象进行单独创建 模式要点: 1.享元模式中的对象分为两部分:共性部分和个性化部分,共性部分就是每个对象都一致的或者多个对象可以共享的部分,个性化部分指差异比较大,每个类均不同的部分 2.共性部分的抽象就是此模

深入浅出设计模式——享元模式(Flyweight Pattern)

模式动机 面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数.当对象数量太多时,将导致运行代价过高,带来性能下降等问题.享元模式正是为解决这一类问题而诞生的.享元模式通过共享技术实现相同或相似对象的重用. 在享元模式中可以共享的相同内容称为内部状态(Intrinsic State),而那些需要外部环境来设置的不能共享的内容称为外部状态(Extrinsic State),由于区分了内部状态和外部状态,因此可以通过设置不同的外部状态使得相同的对象可以具有

设计模式-享元模式

***********************************************声明****************************************************** 原创作品,出自 "晓风残月xj" 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj). 由于各种原因,可能存在诸多不足,欢迎斧正! *******************************************

C#设计模式-享元模式

前言 最近开始花点心思研究下设计模式,主要还是让自己写的代码可重用性高.保证代码可靠性.所谓设计模式,我找了下定义:是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.毫无疑问,设计模式于己于他人于系统都是多赢的:设计模式使代码编制真正工程化:设计模式是软件工程的基石脉络,如同大厦的结构一样. 为什么要提倡“Design Pattern(设计模式)”? 根本原因是为了代码复用,增加可维护性.因此这次我们来学习下设计模式,最后会通过C#语言来实现这些设计模式作为例子,深刻理解其中的

PHP设计模式——享元模式

声明:本系列博客参考资料<大话设计模式>,作者程杰. 享元模式使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件.通常物件中的部分状态是可以分享.常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元. UML类图: 角色分析: 享元工厂角色(FWFactory):创建并管理BlogModel对象. 所有具体享元父接口角色(BolgModel):接受并作用与外部状态. 具体享元角色(JobsBlog)