设计模式 <结构型型> | 享元模式

享元模式(Flyweight Design Pattern)

享元模式的意图是复用对象,节省内存,当一个系统中存在大量重复对象的时候,就可以利用享元模式,将对象设计成享元,在内存中只保留一份实例,供多处代码引用,这样可以减少内存中对象的数量,以起到节省内存的目的。

享元模式把一个对象的状态分成内部状态和外部状态,常量数据称内在状态,其他对象只可以读取不可以修改。可以随着环境变动的称外部状态,外部状态通常由客户端保存,并在享元对象创建后,需要的时候传入享元对象内部。

结构图:

角色:

  1. 抽象享元(IFlyweight),接口或抽象类,声明了具体享元类公共方法,可以向外界提供享元对象的内部数据,也可以通过这些方法来设置外部数据。
  2. 具体享元(ConcreteFlyweight),实现抽象角色定义。
  3. 适配器(Adapter),管理享元对象池和创建享元对象。

适用场景:

  1. 有大量享受对象时。

优点:

  1. 避免重复创建相似对象,节约内存空间。

缺点

  1. 外部状态会提高代码复杂度,在多线程使用还需要关注线程安全问题。

代码(C#)

譬如有1、2、3个不可变的对象需要复用,就可以使用享元模式,省去了创建对象的过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

var t = NumberFactory.GetNumber(1);
t.Operation("111");


/// <summary>
/// 抽象享元角色
/// </summary>
public interface IOperation
{
void Operation(string extrinsicState);
}

/// <summary>
/// 享元角色
/// </summary>
public class Number : IOperation
{
private int number { get; set; }

public Number(int number)
{
this.number = number;
}

public void Operation(string extrinsicState)
{
Console.WriteLine(extrinsicState);
}
}

/// <summary>
/// 享元工厂
/// </summary>
public class NumberFactory
{
private static Dictionary<int, Number> _ls = new()
{
{ 1, new Number(1) },
{ 2, new Number(2) },
{ 3, new Number(3) }
};

public static Number GetNumber(int number)
{
return _ls[number];
}
}

最后

享元模式看起来和单例差不多,但是有本质的区别,在单例模式中,一个类只能创建一个对象,而在享元模式中,一个类可以创建多个对象,每个对象被多处代码引用共享。
对象池、连接池、线程池也是为了复用,但是和享元模式还是有区别的。在任意时刻,每一个对象、连接、线程,并不会被多处使用,而是被一个使用者独占,当使用完成之后,放回到池中,再由其他使用者重复利用。享元模式中在整个生命周期中,都是被所有使用者共享的,主要目的是节省空间。


设计模式 <结构型型> | 享元模式
http://example.com/posts/65163.html
作者
她微笑的脸y
发布于
2023年3月6日
许可协议