定义
享元模式以共享的方式高效的支持大量的细粒度对象。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
内蕴状态存储在享元内部,不会随环境的改变而有所不同,是可以共享的
外蕴状态是不可以共享的,它随环境的改变而改变的,因此外蕴状态是由客户端来保持(因为环境的变化是由客户端引起的)。
UML
单纯享元模式的结构。
1) 抽象享元角色:为具体享元角色规定了必须实现的方法,而外蕴状态就是以参数的形式通过此方法传入。在Java中可以由抽象类、接口来担当。
2) 具体享元角色:实现抽象角色规定的方法。如果存在内蕴状态,就负责为内蕴状态提供存储空间。
3) 享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键!
4) 客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外蕴状态。
怎么咋看咋像简单工厂模式呢!没错,可以说结构型的单纯享元模式和创建型的简单工厂模式实现上非常相似,但是它的重点或者用意却和工厂模式截然不同。工厂模式的使用主要是为了使系统不依赖于实现得细节(见《深入浅出工厂模式》);而在享元模式的主要目的如前面所述:采用共享技术来避免大量拥有相同内容对象的开销。正所谓“旧瓶装新酒”阿!
复合享元模式的结构。
1) 抽象享元角色:为具体享元角色规定了必须实现的方法,而外蕴状态就是以参数的形式通过此方法传入。在Java中可以由抽象类、接口来担当。
2) 具体享元角色:实现抽象角色规定的方法。如果存在内蕴状态,就负责为内蕴状态提供存储空间。
3) 复合享元角色:它所代表的对象是不可以共享的,并且可以分解成为多个单纯享元对象的组合。
4) 享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键!
5) 客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外蕴状态。
统比一下单纯享元对象和复合享元对象,里面只多出了一个复合享元角色,但是它的结构就发生了很大的变化。我们还是使用类图来表示下:
你也许又纳闷了,这个也似曾相逢!单看左半部,和简单工厂模式类似;再看右半部,怎么这么像合成模式呢(请参看关于合成模式的文章或者期待我的《深入浅出合成模式》)!合成模式用在此处就是为了将具体享元角色和复合享元角色同等对待和处理,通过将享元模式与合成模式组合在一起,可以确保复合享元中所包含的每个单纯享元都具有相同的外蕴状态,而这些单纯享元的内蕴状态往往是不同的。
实例
假如我们要开发一个类似MS Word的字处理软件,下面分析一下将如何来实现。对于这样一个字处理软件,它需要处理的对象既有单个字符,又有由字符组成的段落以及整篇文档,根据面向对象的设计思想,不管是字符、段落还是文档都应该作为单个的对象去看待。我们暂不考虑段落和文档对象,只考虑单个的字符,于是可以很容易的得到下面的结构图:
//抽象的字符类 public abstract class Charactor{ //属性 protected char letter; protected int fontsize; //显示方法 public abstract void display(); } //具体的字符类A public class CharactorA extends Charactor{ //构造函数 public CharactorA(){ this.letter = 'A'; this.fontsize = 12; } //显示方法 public void display(){ try{ System.out.println(this.letter); }catch(Exception err){ } } } //具体的字符类B public class CharactorB extends Charactor{ //构造函数 public CharactorB(){ this.letter = 'B'; this.fontsize = 12; } //显示方法 public void display(){ try{ System.out.println(this.letter); }catch(Exception err){ } } }
我们的这段代码完全符合面向对象的思想,但是却为此搭上了太多的性能损耗,代价很昂贵。
一篇文档的字符数量很可能达到成千上万,甚至更多,那么在内存中就会同时存在大量的Charactor对象,这时候的内存开销可想而知。
我们把这些不可共享的状态仍然保留在Charactor对象中,把不同的状态通过参数化的方式,由客户程序注入。letter为内蕴,fontsize为外韵
public abstract class Charactor{ //属性 protected char letter; protected int fontsize; //显示方法 public abstract void display(); //设置字体大小 public abstract void setFontSize(int fontsize); } //具体的字符类A public class CharactorA extends Charactor{ //构造函数 public CharactorA(){ this.letter = 'A'; this.fontsize = 12; } //显示方法 public void display(){ try{ System.out.println(this.letter); }catch(Exception err){ } } //设置字体大小 public void setFontSize(int fontsize){ this.fontsize = fontsize; } } //具体的字符类B public class CharactorB extends Charactor{ //构造函数 public CharactorB(){ this.letter = 'B'; this.fontsize = 12; } //显示方法 public void display(){ try{ System.out.println(this.letter); }catch(Exception err){ } } //设置字体大小 public void setFontSize(int fontsize){ this.fontsize = fontsize; } } //客户程序 public class ClinetTest{ public static void main(String[] args){ Charactor a = new CharactorA(); Charactor b = new CharactorB(); //设置字符A的大小 a.setFontSize(12); //显示字符B a.display(); //设置字符B的大小 b.setFontSize(14); //显示字符B b.display(); } }
优点
享元模式优点就在于它能够大幅度的降低内存中对象的数量
缺点
享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。
享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。
使用场景
一个应用程序使用了大量的对象。 完全由于使用大量的对象,造成很大的存储开销。 对象的大多数状态都可变为外部状态。 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。且 应用程序不依赖对象标识。
以上内容部分摘自:http://blog.csdn.net/ai92/article/details/224598
相关推荐
JAVA-设计模式-结构型模式-享元模式
c++设计模式-结构型模式-享元模式;qt工程;c++简单源码; 享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类...
设计模式面面观(14):享元模式(Facade Pattern)-结构型模式 http://blog.csdn.net/fanweiwei/archive/2008/04/25/2326692.aspx
设计模式_结构型_享元模式
C#面向对象设计模式纵横谈(12):Flyweight 享元模式(结构型模式) (Level 300)
软件设计模式2021秋-实验2-结构型模式实验报告附源码和类图.zip 桥接模式、适配器模式、装饰者模式、组合模式、享元模式
在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要... 这是第12节:结构型模式Flyweight享元模式
设计模式10-代理模式、结构型模式大复习 设计模式11-行为模式-责任链、命令模式 设计模式12-解释器模式 设计模式13-迭代器模式 设计模式14-中介者模式、备忘录模式 设计模式15-观察者模式、状态模式 设计模式16-策略...
桥接模式之消息发送、适配器模式之购物车商品推荐、装饰者模式之相亲(男人的描述)、组合模式之对购物网站、享元模式之网店模板
C#面向对象设计模式纵横谈(12):Flyweight 享元模式(结构型模式)
享元模式:在天猫商城里存在着成天上万的网店,但是天猫所提供的网站模板是一样的,存在许多天猫网店使用同一个网店模板的情况,如果每一个网店都用一个网店对象来表示,因为网店数量巨大,我们需求很
包含5个实验,桥接模式(电子商务网站常有这样的功能:发送消息通知,比如订货...),享元模式(在天猫商城里存在着成天上万的网店,但是天猫所提供的网站模板是一样的,存在许多天猫网店使用同一个网店模板的情况)
NULL 博文链接:https://jacky-dai.iteye.com/blog/2302888
桥接模式之消息发送、适配器模式之购物车商品推荐、装饰者模式之相亲(男人的描述)、组合模式之对购物网站、享元模式之网店模板
享元模式(Flyweight Pattern) 12. 代理模式(Proxy Pattern) 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 行为型: 16. 观察者模式(Observer Pattern...
资源中包括7个实验的源代码和报告。源代码可运行,报告中包括实现类图。结构型设计模式:适配器模式 代理模式 桥接模式 装饰模式 组合模式 外观模式 享元模式
享元模式主要是对其数据、方法共享分离,将数据和方法分成内部数据、内部方法和外部数据、外部方法。内部方法与内部数据指的是相似或共有的数据和方法,所以将其提取出来减少开销。 var Flyweight = function() { ...