设计模式-结构型-享元模式(缓存模式,Cache,Flyweight)
通过共享多个对象所共有的相同状态, 使有限的内存容量中载入更多对象。
文章目录
前言
基于面向对象编程的思想,当系统中的类和对象的个数太多时,导致大量性能被损耗,享元模式可以解决性能下降的问题。
一、享元模式(缓存共享对象,降低内存消耗)
享元模式(轻量级模式),是对象池的一种实现,类似于线程池(线程池可以避免不停的创建和销毁对象的性能损耗),享元模式通过减少对象数量,达到改善应用所需的对象结构的方式,减少性能损耗。
享元模式将对象的状态分为(内部状态:对象内部状态是稳定不变的)和(外部状态:对象外部状态是可变化的),通过共享内部状态达到减少对象数量节约内存的目的。
二、应用场景
- 常应用与系统底层的开发,以解决系统性能的问题
- 系统有大量相似对象,需要缓冲池的场景
三、角色
- 抽象享元角色(IFlyweight): 享元对象的抽象基类或接口,定义对象内部及外部状态的抽象。
- 具体享元角色(ConcreteFlyweight):实现抽象享元角色定义的业务。
- 享元工厂(FlyweightFactory):管理享元对象池和创建享元对象
四、使用步骤
1.抽象享元
代码如下(示例):抽象享元方法
/// <summary>
/// 抽象享元
/// </summary>
public interface IFlyweight
{
void operation(string extrinsicState);
}
2.具体享元
代码如下(示例):完成具体享元实现
/// <summary>
/// 具体享元
/// </summary>
public class ConcreteFlyweight : IFlyweight
{
private string intrinsicState;
public ConcreteFlyweight(string str)
{
this.intrinsicState = str;
}
public void operation(string extrinsicState)
{
Console.WriteLine($"Object address:{this.intrinsicState.GetHashCode()}");
Console.WriteLine($"intrinsicState:{this.intrinsicState}");
Console.WriteLine($"str:{extrinsicState}");
}
}
3.创建享元工厂(重点)
代码如下(示例):享元工厂,定义享元对象池
/// <summary>
/// 享元工厂(创建对象)
/// </summary>
public class FlyweightFactory
{
private static Dictionary<string, IFlyweight> pool = new Dictionary<string, IFlyweight>();
/// <summary>
/// 获取IFlyweight的对象
/// </summary>
/// <param name="intrinsicState"></param>
/// <returns></returns>
public IFlyweight getFlyweight(string intrinsicState)
{
if (!pool.ContainsKey(intrinsicState))
{
Console.WriteLine($"Dictionary 不包含 key 为{intrinsicState} 的 IFlyweight 对象");
IFlyweight fw = new ConcreteFlyweight(intrinsicState);
pool.Add(intrinsicState, fw);
}
else
{
Console.WriteLine($"Dictionary 包含 key 为{intrinsicState} 的 IFlyweight 对象,开始去查询");
}
return pool.Where(p => p.Key.Equals(intrinsicState)).FirstOrDefault().Value;
}
}
4.客户端调用
代码如下(示例):
/// <summary>
/// 享元调用者
/// </summary>
public class FlyweightClient
{
public void client()
{
FlyweightFactory ff = new FlyweightFactory();
IFlyweight ifw = ff.getFlyweight("aa");
IFlyweight ifws = ff.getFlyweight("aa");
IFlyweight ifw2 = ff.getFlyweight("abb");
ifw.operation("a");
ifws.operation("a");
ifw2.operation("b");
}
}
5.Run 结果
代码如下(示例):
享元模式
Dictionary 不包含 key 为aa 的 IFlyweight 对象
Dictionary 包含 key 为aa 的 IFlyweight 对象,开始去查询
Dictionary 不包含 key 为abb 的 IFlyweight 对象
Object address:-630000639
intrinsicState:aa
str:a
Object address:-630000639
intrinsicState:aa
str:a
Object address:1214818789
intrinsicState:abb
str:b
该处使用的url网络请求的数据。
总结
优点
- 有效的减少了对象的创建(享元对象池),降低了内存中对象的数量,降低了系统的内存,提供效率。
- 减少对象的创建,导致内存之外的其他资源占用也被降低。
缺点
- 关注内部,外部状态,关注线程安全问题
- 使用系统,程序的逻辑复杂化。