享元模式:解决对象的复用问题,提供第三方的管理,不破坏类的封装
自行实例化对象,不像单例时强制保证
池化资源管理:
享元工厂也可以初始化多个对象---其他地方需要使用对象可以找工厂拿(修改个状态)--用完之后在放回来(状态修改回来)
避免重复的创建和销毁资源(特别是对于非托管资源,像:数据库连接,线程)
享元模式:
1.实现一:
public class FlyweightFactory
{
private static Dictionary<WordType, BaseWorld> FlyweightFactoryDictionary = new Dictionary<WordType, BaseWorld>();
/// <summary>
/// 1.如果是5个线程同时调用,字典为空,所以会同时构造5次E
/// 2.最后只只打印一个ELEVEN,因为其他线程都挂掉了,因为在字典中添加相同的值的时候,挂掉了
/// 3. 2个L是小概率事件,前两个线程是同时添加E,所以没有失败,所以L有两个,但是到L的时候又冲突了
/// 4.子线程的异常时看不到的,除非waitall
/// </summary>
/// <param name="wordType"></param>
/// <returns></returns>
public static BaseWorld CreateWord(WordType wordType)
{
if (!FlyweightFactoryDictionary.ContainsKey(wordType))
{
BaseWorld word = null;
switch (wordType)
{
case WordType.E:
word = new E();
break;
case WordType.L:
word = new L();
break;
case WordType.V:
word = new V();
break;
case WordType.N:
word = new N();
break;
default:
throw new Exception();
}
FlyweightFactoryDictionary.Add(wordType, word);
}
return FlyweightFactoryDictionary[wordType];
}
}
public enum WordType
{
E,
L,
V,
N
}
测试代码:
for (int i = 0; i < 5; i++)
{
Task.Run(() =>
{
BaseWorld e = FlyweightFactory.CreateWord(WordType.E);
BaseWorld l = FlyweightFactory.CreateWord(WordType.L);
BaseWorld V = FlyweightFactory.CreateWord(WordType.V);
BaseWorld n = FlyweightFactory.CreateWord(WordType.N);
Console.WriteLine("{0}{1}{2}{3}{4}{5}", e.Get(), l.Get(), e.Get(), V.Get(), e.Get(), n.Get());
});
}
测试结果:
2.实现方式二:
public class FlyweightFactory
{
private static Dictionary<WordType, BaseWorld> FlyweightFactoryDictionary = new Dictionary<WordType, BaseWorld>();
/// <summary>
/// 不想看到多线程的时候生成多个E,加锁
/// </summary>
private readonly static object FlyweightFactoryLock = new object();
/// <summary>
/// 1.如果是5个线程同时调用,字典为空,所以会同时构造5次E
/// 2.最后只只打印一个ELEVEN,因为其他线程都挂掉了,因为在字典中添加相同的值的时候,挂掉了
/// 3. 2个L是小概率事件,前两个线程是同时添加E,所以没有失败,所以L有两个,但是到L的时候又冲突了
/// 4.子线程的异常时看不到的,除非waitall
/// </summary>
/// <param name="wordType"></param>
/// <returns></returns>
public static BaseWorld CreateWord(WordType wordType)
{
if (!FlyweightFactoryDictionary.ContainsKey(wordType))
//是为了性能优化,避免对象已经被初始化后,再次请求还需要等待锁
{
lock (FlyweightFactoryLock)//相当于Monitor.Enter, 保证方法体只有一个线程可以进入
{
if (!FlyweightFactoryDictionary.ContainsKey(wordType))
{
BaseWorld word = null;
switch (wordType)
{
case WordType.E:
word = new E();
break;
case WordType.L:
word = new L();
break;
case WordType.V:
word = new V();
break;
case WordType.N:
word = new N();
break;
default:
throw new Exception();
}
FlyweightFactoryDictionary.Add(wordType, word);
}
}
}
return FlyweightFactoryDictionary[wordType];
}
}
public enum WordType
{
E,
L,
V,
N
}
测试结果: