设计模式-享元模式
定义:运用共享技术来有效的支持大量细粒度对象的复用。它通过共享技术来大幅度的减少需要创建的对象数量,避免大量相似类的开销,从而提升系统资源的利用率。
享元模式的目的在于运用共享技术,是的一些细粒度的对象可以共享,多使用细粒度的对象,便于重用或重构。
享元模式的一个重要运用就是复用池、缓存池。
享元模式的通用类图如下
Flyweight 抽象享元角色
产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现
Concrete Flyweight 具体享元角色
具体的产品类,实现抽象角色定义的业务,该角色需要注意的是内部状态处理应该与环境无关,不应该出现一个操作改变了内部状态,同时修改了外部状态。
unsharedConcreteFlyweight 不可共享的享元角色
一般不会出现在享元工厂中
FlyweightFactory 享元工厂
构造一个池容器,同时提供从池中获得的方法
以饭店餐桌为例,客人是流动的,但是每张餐桌只需要创建一个,且同一时刻,一个餐桌只服务一批客户。当前一批客户结账走人后,可以继续使用这个餐桌服务下一批客户。
代码实现如下
Flyweight 享元抽象、接口类如下
// 餐桌抽象享元接口
public interface ITableFlyweight
{
// 餐桌状态
int State { get; set; }
// 餐桌key
string Key { get; set; }
void SetState(int state);
int GetState();
}
Concrete Flyweight 具体享元角色
// 大厅的餐桌
public class HallTableFlyweight : ITableFlyweight
{
public int State { get; set; }
public string Key { get; set; }
public void SetState(int state)
{
State = state;
}
public int GetState()
{
return State;
}
}
// 雅间的餐桌
public class PrivateRoomTableFlyweight : ITableFlyweight
{
public int State { get; set; }
public string Key { get; set; }
public void SetState(int state)
{
State = state;
}
public int GetState()
{
return State;
}
}
FlyweightFactory 享元工厂
// 享元工厂
public class FlyweightFactory
{
private Dictionary<string, ITableFlyweight> tableDic = null;
public FlyweightFactory()
{
tableDic = new Dictionary<string, ITableFlyweight>();
}
// 添加享元对象
public void Add(string key, ITableFlyweight flyweight)
{
//
if (!tableDic.ContainsKey(key))
{
tableDic.Add(key, flyweight);
}
}
// 获取享元对象
public ITableFlyweight Get(string key)
{
ITableFlyweight flyweight = null;
tableDic.TryGetValue(key, out flyweight);
return flyweight;
}
}
调用如下
public class Hotel
{
public Hotel()
{
// 创建享元工厂
FlyweightFactory flyweightFactory = new FlyweightFactory();
// 创建享元对象
HallTableFlyweight hallTableFlyweight1 = new HallTableFlyweight();
hallTableFlyweight1.Key = "大厅1号桌";
// 将对象添加到享元工厂
flyweightFactory.Add("大厅1号桌", hallTableFlyweight1);
// 创建享元对象
HallTableFlyweight hallTableFlyweight2 = new HallTableFlyweight();
hallTableFlyweight2.Key = "大厅2号桌";
// 将对象添加到享元工厂
flyweightFactory.Add("大厅2号桌", hallTableFlyweight2);
// 创建享元对象
HallTableFlyweight hallTableFlyweight3 = new HallTableFlyweight();
hallTableFlyweight3.Key = "大厅3号桌";
// 将对象添加到享元工厂
flyweightFactory.Add("大厅3号桌", hallTableFlyweight3);
// 创建享元对象
PrivateRoomTableFlyweight privateRoomTableFlyweight1 = new PrivateRoomTableFlyweight();
privateRoomTableFlyweight1.Key = "剑桥";
// 将对象添加到享元工厂
flyweightFactory.Add("剑桥", privateRoomTableFlyweight1);
// 创建享元对象
PrivateRoomTableFlyweight privateRoomTableFlyweight2 = new PrivateRoomTableFlyweight();
privateRoomTableFlyweight2.Key = "牛津";
// 将对象添加到享元工厂
flyweightFactory.Add("牛津", privateRoomTableFlyweight2);
// 创建享元对象
PrivateRoomTableFlyweight privateRoomTableFlyweight3 = new PrivateRoomTableFlyweight();
privateRoomTableFlyweight3.Key = "哈佛";
// 将对象添加到享元工厂
flyweightFactory.Add("哈佛", privateRoomTableFlyweight3);
ITableFlyweight flyweight1 = flyweightFactory.Get("大厅1号桌");
Console.WriteLine(flyweight1.Key + "\n");
ITableFlyweight flyweight2 = flyweightFactory.Get("大厅2号桌");
Console.WriteLine(flyweight2.Key + "\n");
ITableFlyweight flyweight3 = flyweightFactory.Get("大厅3号桌");
Console.WriteLine(flyweight3.Key + "\n");
ITableFlyweight flyweight4 = flyweightFactory.Get("剑桥");
Console.WriteLine(flyweight4.Key + "\n");
ITableFlyweight flyweight5 = flyweightFactory.Get("牛津");
Console.WriteLine(flyweight5.Key + "\n");
ITableFlyweight flyweight6 = flyweightFactory.Get("哈佛");
Console.WriteLine(flyweight6.Key + "\n");
}
}
执行结果
优点:
(1) 大大减少了对象的创建,降低了程序内存的占用,提高效率
缺点:
(1) 提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变