c#设计模式系类:亨元模式
一、引言
在软件开发过程中,如果我们需要重复使用某个对象的时候,如果我们重复地使用new创建这个对象的话,这样我们在内存就需要多次去申请内存空间了,这样可能出现内存使用越来越多的情况,这样的问题是非常严重,然而亨元模式可以解决这个问题,下面我们一起具体看看亨元模式是如何解决这个问题的。
二、享元模式的详细介绍
既然亨元模式可以解决重复使用new创建对象的问题,下面让我们分析下如何去解决上面那个问题,既然都是同一个对象,能不能只创建一个对象,然后下次需要创建这个对象的时候,让它直接用已经创建好了的对象就好了呢,也就是说让一个对象共享。这个也是亨元模式的实现精髓所在。
2.1 定义
介绍完享元模式的精髓之后,让我们具体看看享元模式的正式定义:
亨元模式——利用共享技术有效地支持大量细粒度的类实例来表示数据,亨元模式可以避免大量相识类的开销,在软件开发过程中如果需要大量细粒度的类实例来表示数据,而这些实例除了几个参数外基本相同,这时候就可以使用亨元模式来大幅度减少需要类的实例数量。如果能把这些参数(指的这些类实例的不同参数)移动到类实例外面,在方法调用时将他们传入尽量,这样就可以通过共享大幅度减少单个实例的数目,然而我们把类实例外面的参数称为亨元对象的外部状态,把亨元对象内部参数称为内部状态,
- 内部状态:在亨元对象的内部,并且不会随着环境的改变而改变的共享部分
- 外部对象:随环境的变化而改变的,部可以共享的部分。
2.2 亨元模式结构图

2.3 亨元模式的组成
- 抽象亨元角色(Flyweight):此角色是所有的具体亨元类的基类,为这些类规定出需要实现的公共接口,那些需要外部状态的操作可以通过调用方法已参数形式传递。
- 具体亨元角色(ConcreteFlyweight):实现抽象亨元角色所规定的接口,如果又内部状态的化,可以在类内部定义。
- 亨元工厂角色(FlyweightFactory):本角色负责创建和管理亨元角色,本角色保证亨元对象可以被共享,当一个客户端调用一个亨元对象的时候,亨元工厂角色检查系统是否已经有一个符合的亨元对象,如果已经存在,就返回亨元对象,如果不存在就重新创建一个亨元对象
- 客户端角色(Client):本角色需要存储亨元对象的外部状态
2.4亨元模式代码实现
Flyweight类,它是所有具体亨元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态

public abstract class Flywieght
{
public abstract void Operation(int extrinsicstate);
}
ConcreteFlyweight是继承Flyweight超类或实现Flyweight接口,并为内部状态增加存储空间。

public class ConcreteFlyweight:Flywieght
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("具体的"+extrinsicstate);
}
}
UnsharedConcreteFlyweight是 指那些不需要共享的Flyweight子类,因为Flyweight接口让共享成为可能,但它并不强制共享

public class UnsharedConcreteFlyweight:Flywieght
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("不共享的具体Flywieght"+extrinsicstate);
}
}
FlyweightFactory,是一个亨元工厂,用来创建并管理Flyweight对象,它主要是用来确保合理的共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在)

public class FlyweightFactory
{
private Hashtable flyweights = new Hashtable(); public FlyweightFactory()
{
flyweights.Add("X",new ConcreteFlyweight());
flyweights.Add("Y", new ConcreteFlyweight());
flyweights.Add("Z", new ConcreteFlyweight());
}
public Flywieght GetFlyweight(string key)
{
return ((Flywieght)flyweights[key]) ;
}
}
客户端代码

class Program
{
static void Main(string[] args)
{
int extrinsincstate = 10;
FlyweightFactory f = new FlyweightFactory(); Flywieght fx = f.GetFlyweight("X");
fx.Operation(--extrinsincstate); Flywieght fy = f.GetFlyweight("Y");
fy.Operation(--extrinsincstate); Flywieght fz = f.GetFlyweight("Z");
fz.Operation(--extrinsincstate); UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight();
uf.Operation(--extrinsincstate); Console.Read();
}
}
结果表示

具体的9
具体的8
具体的7
不共享的具体Flywieght6
三、享元模式的实现要点:
面向对象很好地解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight设计模式主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。
Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理。
对象的数量太大从而导致对象内存开销加大——什么样的数量才算大?这需要我们仔细的根据具体应用情况进行评估,而不能凭空臆断。
- 享元模式的优点
- 享元模式的优点在于它能够极大的减少系统中对象的个数。
- 元模式由于使用了外部状态,外部状态相对独立,不会影响到内部状态,所以享元模式使得享元对象能够在不同的环境被共享。
- 享元模式的缺点
- 于享元模式需要区分外部状态和内部状态,使得应用程序在某种程度上来说更加复杂化了。
- 为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变
- 在下面所有条件都满足时,可以考虑使用享元模式:
- 一个系统中有大量的对象;
- 这些对象耗费大量的内存;
- 这些对象中的状态大部分都可以被外部化
- 这些对象可以按照内部状态分成很多的组,当把外部对象从对象中剔除时,每一个组都可以仅用一个对象代替软件系统不依赖这些对象的身份,
满足上面的条件的系统可以使用享元模式。但是使用享元模式需要额外维护一个记录子系统已有的所有享元的表,而这也需要耗费资源,所以,应当在有足够多的享元实例可共享时才值得使用享元模式。
通过迭代来使用模式,别为了模式而模式
c#设计模式系类:亨元模式的更多相关文章
- Java设计模式之亨元模式
之前在项目中接触过亨元模式这一种设计模式,当时因为项目赶进度,因此只不过是大概的了解了一下,刚好今天有时间,就写一篇博客详细的学习一下亨元模式. 一.概念 运用共享技术有效的支持大量细粒度的对象.(来 ...
- 设计模式 -- 亨元模式(FlyWeight Pattern)
用来尽可能减少内存使用量,适用于存在大量重复对象的场景,达到对象共享,避免创建过多对象的效果,提升性能,避免内存溢出. 定义: 使用共享对象有效支持大量细粒度对象. 适用场景: 系统中存在大量相似对象 ...
- Java设计模式之《享元模式》及应用场景
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6542449.html 享元模式:"享"就是分享之意,指一物被众人共享, ...
- 面向对象设计模式之Flyweight享元模式(结构型)
动机:采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行代价——主要指内存需求方面的代价.如何在避免大量细粒度对象问题的同 时,让外部客户程序仍然能够透明地使用面向对象的 ...
- 设计模式学习之享元模式(Flyweight,结构型模式)(20)
转:http://terrylee.cnblogs.com/archive/2006/03/29/361767.html 摘要:面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题.但是 ...
- 设计模式学习心得<享元模式 Flyweight>
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式. 享元模式尝 ...
- C#设计模式之十一享元模式(Flyweight Pattern)【结构型】
一.引言 今天我们要讲[结构型]设计模式的第六个模式,该模式是[享元模式],英文名称是:Flyweight Pattern.还是老套路,先从名字上来看看.“享元”是不是可以这样理解,共享“单元”,单元 ...
- Java设计模式学习记录-享元模式
前言 享元模式也是一种结构型模式,这篇是介绍结构型模式的最后一篇了(因为代理模式很早之前就已经写过了).享元模式采用一个共享来避免大量拥有相同内容对象的开销.这种开销最常见.最直观的就是内存损耗. 享 ...
- 设计模式(11)--Flyweight(享元模式)--结构型
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.模式定义: 享元模式是对象的结构模式.享元模式以共享的方式高效地支持大量的细粒度对象. 2.模式特点: 享元模 ...
随机推荐
- leetcode535
public class Codec { const string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW ...
- 数字1的ASCII值是多少
ASCII表是计算机将字符转为数字存储的一张转换表.因此,只有字符才有ASCII值,数字是没有的. 答案:数字1没有ASCII值,数字1在计算机中就是按数值1存储的. 字符1的ASCII值是 49
- 如何建立ElasticSearch里的mappings?
刚接触elasticsearch,好多东西都不会用,百度了很多,都看不懂,终于摸索出了最简单的通过http建立mappings的方法~ 有人在建立mappings报各种错误,首先,如果你的这个索引中已 ...
- 运动函数封装(js)
// 运动函数 function starMove(obj,json,fnEnd){ clearInterval(obj.timer); obj.timer = setInterval(functi ...
- Java中Final修饰一个变量时,是引用不能变还是引用的对象不能变
Java中,使用Final修饰一个变量,是引用不能变,还是引用对象不能变? 是引用对象的地址不能变,引用变量所指的对象的内容可以改变. final变量永远指向这个对象,是一个常量指针,而不是指向常量的 ...
- 开发微信小程序入门教程,含破解工具
2016年09月21日晚 微信发不了微信“小程序”的内测版,一时间整个互联网都炸了锅.个大新闻.论坛都在讨论这个事情. 作为互联网的一猿,我们怎能不紧跟时代的脚步.于是第二天上午也对微信发布的“小程序 ...
- JAVA的StringBuffer类[转]
StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存 ...
- java读取properties配置文件[转]
网上文章常见的几种读取.properties文件的方式 1.使用java.util.Properties类的load()方法 示例: InputStream in = lnew BufferedInp ...
- [C++] const inside class VS const outside class
const inside class VS const outside class 类内:类内的const和c语言一样,可以通过指针间接修改const变量的值,读内存,一开始必须初始化 类外:虽然可以 ...
- [C++] decltype(auto) C++ 11 feature
1 //C++ 11 feature template <class T1, class T2> auto getMultiply(T1 data1, T2 data2) -> de ...