前言

享元模式,表面意思是共享单元,属于结构型设计模式。哦?good啊,如今共享文化高大上,共享肯定节约很多资源吧,肯定用的地方挺多吧,然而并不多,但是又是不可或缺的一种模式。 至于为什么,请看正文部分,将会通过计算分析出为什么用的地方不多,或者说有些地方为什么不该用,同时得出为什么属于结构型,到底属于结构型的哪一种。

开车触发

介绍一下什么是结构型: 结构型模式所描述的是如何将类和对象结合在一起来形成一个更大的结构,它描述两种不同的事物:类和对象,根据这一点,可分为类结构型和对象结构型模式。类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系;对象结构型模式关心类与对象的组合,通过关联关系使得在一个类中定义另一个类的实例对象,然后通过该对象调用其方法。根据“合成复用原则”,在系统中尽量使用关联关系来替代继承关系,因此大部分结构型模式都是对象结构型模式。 好了,先对结构型有一个小小的概念,然后出发吧。 有一个Font,字体类。

public class Font{// uniqueprivate string key;//表示字体大小private int size;//表示字体颜色private string color;public Font(string key, int size,string color){this.key = key;this.size = size;this.color = color;}}

一个对字体进行渲染的静态类。

public static class render{public static void renderFont(char a,Font font) {//进行字体渲染}}

main 中调用

static void Main(string[] args){Font fontx = new Font("xxx",12,"red");render.renderFont('a',fontx);Font fonty = new Font("yyy", 13, "red");render.renderFont('b',fonty);Font fontx2 = new Font("xxx", 12, "red");render.renderFont('c',fontx2);}

如果仔细看下main中,会发现我渲染了两个相同的:

Font fontx = new Font("xxx",12,"red");

我这是描述渲染过程,比如我们在渲染文章的时候是一个一个输出,根本就不知道下一个要输出什么,它的字体类型是什么。 上面描述的过程是当前字体类型为fontx,我写下了a,然后使用字体fonty,去描述b,最后我有用字体fontx2(和fontx相同配置)去渲染c。 如此下去会有一个什么问题呢?假设有10万字需要渲染。 先查下Font 实例会占用多少个byte。 在Font头部加上StructLayout,使得它按照structLayout 对齐,否则无法取得其大小。

[StructLayout(LayoutKind.Sequential)]public class Font

然后调用:

Font fontx = new Font("xxx",12,"red");unsafe {var byteSize = Marshal.SizeOf(fontx);Console.WriteLine("查询大小");}

查询结果为24字节。 开始计算: 24byte * 110^6=2.410^7 /1024 /1024=2.410^7 /(1.04857610^6)约等于24m. 也就是假设我要渲染10w字我需要24m内存,可想而知,是需要优化的。 那就加上一个工厂类吧:

public class FontFactory{private Hashtable flyweights = new Hashtable();public Font getFont(string key,int size,string color) {if (!flyweights.ContainsKey(key)){flyweights.Add(key,new Font(key,size,color));}return (Font)flyweights[key];}}

调用:

static void Main(string[] args){FontFactory fontFactory = new FontFactory();Font fontx = fontFactory.getFont("xxx",12,"red");Font fonty = fontFactory.getFont("yyy", 13, "red");}

通过一个font生成工厂,如果有的话就提取,没有的话就生成,然后返回。 但是前面提及到了,这种模式使用的少。为什么这么说? 首先,FontFactory的机制需要消耗我们的cpu以及不可忽略的一部分内存。 如果产生的对象消耗只有几k,那么这种优化是几乎没有意义的。 第二呢,可以看到生产出来的Font要符合只读,为何只读呢? 如果需要修改的话,那么也遇不到该问题,之所以不去修改,修改的消耗比较大。 所以场景并不是很多,但是服务器端倒是有那么多的地方使用。注:场景和使用的地方不是一个概念哈。 最后,看下对象结构型的概念。 对象结构型模式关心类与对象的组合,通过关联关系使得在一个类中定义另一个类的实例对象,然后通过该对象调用其方法。根据“合成复用原则”,在系统中尽量使用关联关系来替代继承关系,因此大部分结构型模式都是对象结构型模式。 不言而喻,恰恰符合这种模式的概念。

uml图

后续补上

总结

享元主要用于减少创建对象的数量,以减少内存占用和提高性能。 场景:会产生特别多数量对象,消耗过多内存的情况。


©著作权归作者所有:来自51CTO博客作者独孤一笑的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 【jQuery基础入门】顶级对象$()和jQuery中常用的getter、setter
  2. 面向对象、类和对象、封装---------私有private、this关键字
  3. 【算法与数据结构专场】BitMap算法基本操作代码实现
  4. 如果使用的库不支持异步,可以使用多进程并将其转化为异步对象
  5. 关于获取各种浏览器可见窗口大小的一点点研究
  6. javascript创建对象几种方式
  7. orm操作
  8. 高并发第六弹:线程封闭(ThreadLocal)
  9. Java并发编程学习4-线程封闭和安全发布

随机推荐

  1. ASP.NET MVC中SignalR用法讲解
  2. C++函数与指针
  3. 关于ASP.NET如何利用AjaxPro完成前端跟后
  4. 介绍MVC、MVP和MVVM的区别与用法
  5. 学习asp.net的学习顺序与学习内容分享
  6. asp.net如何利用ashx生成图形验证码的实
  7. ASP.NET中有关Config文件的读写功能讲解
  8. 几种RIA技术介绍
  9. C#中的正则表达式如何验证中文字符的实例
  10. Asp.Net用控件实现本地图片的显示