概念
是池技术的重要实现方式。
运用共享技术有效的支持大量细粒度的对象。
由概念可以看到享元模式对共享对象、细粒度对象由要求。
也就引出了我们可以利用享元模式可以解决什么样的问题这个话题~
享元模式解决什么问题
在由大量对象时,会造成内存溢出,我们需要把共同的部分抽象出来,如果由相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
何时使用
-
系统中存在大量对象,对象消耗大量内存
-
对象的状态可外部化
-
对象按内部划分可以分为组的形式
-
系统不依赖于这些对象的身份—细粒度的对象都具备较接近的外部状态,且内部状态和环境无关,此为对象没有特别身份
-
有需要缓冲池的场景
优点
- 减少对象的创建–降低系统内存–提高效率
缺点
- 因为需要对外部状态和内部状态进行分离,且外部状态具有固化的性质(不随内部状态的变化而变化)所以可能会导致系统的混乱。—复杂型提高
内部状态、外部状态
前面的内容时不时的出现一下内部状态、外部状态,啥是内部状态?外部状态呢?
- 内部状态
对象可以共享出来的信息,存储在享元对象内部并且不会随着环境改变而改变 - 外部状态
外部状态时对象得以依赖的一个标记,随着环境改变而改变,不可以共享的状态。
举个例子:
我们的期末考试,需要有自己的学号,考场号、座位号、以及科目。例如我们校内(非国考)7月第一周周日考试,我们该怎样划分学号、考场号、座位号、科目时内部还是外部状态呢?瞅一哈,好像除了学号时固定不变的以为,剩余的都是可以变化的,可能有人说考场座位号,科目怎么就能变了呢?我们前提非国考的前提下,在校内的这个环境中,考场的变化还是有的,他们会根据实际情况进行调整的不定因素在里面,所以我们把考场号,座位号以及科目划分到外部状态。
结构图
角色说明
-
Flyweight
抽象享元角色
产品的抽象类,同事定义处对象的外部状态和内部状态改的接口或实现。简单说,通过接口此角色能接收并作用于外部状态。 -
ConcreteFlyweight
具体享元角色
具体的产品类,实现抽象角色定义的业务。
为内部状态增加存储空间 -
UnsharedConcreteFlyweight
不可共享的享元角色(不过一般不出现在享元工厂)
?什么样的属于不可共享的享元角色- 不存在外部状态
- 安全要求不能够使用共享技术的对象
-
FlyweightFactory
享元工厂
创建并管理Flyweight对象,构建一个池容器,确保合理的共享Flyweight
实现
- Flyweight
abstract class Flyweight
{
public abstract void Operation(int extrinsicstate);
}
- ConcreteFlyweight
class ConcreteFlyweight : Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine ("具体Flyweight:"+extrinsicstate);
}
}
- UnsharedConcreteFlyweight
class UnsharedConcreteFlyweight:Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("不具体Flyweight:" + extrinsicstate);
}
}
- FlyweightFactory
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 Flyweight GetFlyweight (string key)
{
return ((Flyweight)flyweights[key]);
}
}
- 客户端
static void Main(string[] args)
{
int extrinsicstate = 22;
FlyweightFactory f = new FlyweightFactory();
Flyweight fx = f.GetFlyweight("X");
fx.Operation(--extrinsicstate);
Flyweight fy = f.GetFlyweight("Y");
fx.Operation(--extrinsicstate);
Flyweight fz = f.GetFlyweight("Z");
fx.Operation(--extrinsicstate);
Flyweight uf = new UnsharedConcreteFlyweight();
uf.Operation(--extrinsicstate);
Console.Read();
}