享元模式(Flyweight Pattern)
典型的享元模式的例子为文书处理器中以图形结构来表示字符。一个做法是,每个字形有其字型外观, 字模 metrics, 和其它格式资讯,但这会使每个字符就耗用上千字节。取而代之的是,每个字符参照到一个共享字形物件,此物件会被其它有共同特质的字符所分享;只有每个字符(文件中或页面中)的位置才需要另外储存。
示例
结构图
时序图
class WebSite
{
private string name = "";
private WebSite(string name)
{
this.name = name;
}
public void Use()
{
Console.WriteLine("网站分类" + name);
}
}
客户端代码
static void Main(string args)
{
WebSite fx = new WebSite("产品展示");
fx.Use();
WebSite fy = new WebSite("产品展示");
fy.Use();
WebSite f1 = new WebSite("博客");
f1.Use();
WebSite f2 = new WebSite("博客");
f2.Use();
Console.Read();
}
网站抽象类
abstract class WebSite
{
public abstract void Use();
}
网站工厂类
//网站工厂
class WebSiteFactory
{
private HashTable flyweights = new Hashtable();
//获得网站分类
public WebSite GetWebSiteCategory(string key)
{
flyweights.Add(key, new ConcreteWebSite(key));
return ((WebSite)flyweights[key]);
}
//获得网站分类总数
{
return flyweights.Count;
}
}
客户端代码
static void Main(string[] args)
{
WebSiteFactory f = new WebSiteFactory();
WebSite fx = f.GetWebSiteCategory("产品展示");
fx.Use();
WebSite fy = f.GetWebSiteCategory("产品展示");
fy.Use();
WebSite f1 = f.GetWebSiteCategory("博客");
f1.Use();
WebSite f2 = f.GetWebSiteCategory("博客");
f2.Use();
}
实际上,享元模式可以避免大量非常详细类的开销。在程序设计中,有时需要生成大量细力度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够受大幅度地减少需要实例化的类的数量。如果能把这些蚕食移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。
用户类,用于网站的客户端账号,是”网站”类的外部状态
//用户
public class User
{
private string name;
public User(string name)
{
this.name = name;
}
public string name
{
get {return name;}
}
}
网站抽象类
具体网站类
class ConcreteWebSite: WebSite
{
private string name = "";
public ConcreteWebSite(string name)
{
this.name = name;
}
public override void Use(Use user)
Console.WriteLine("网站分类:" + name + "用户:" + user.name);
}
class WebSiteFactory
{
private Hashtable flyweights = new HashTable();
//获得网站分类
public WebSite GetWebSiteCateegory(string key)
{
if (!flyweights.ContainsKey(key))
flyweights.Add(key, new ConcreteWebSite(key));
return ((webSite)flyweightskey[key]);
}
//获得网站分类总数
public int GetWebSiteCount
{
return flyweights.Count;
}
}
客户端代码
static void Main(string[] args)
{
WebSiteFactory f = new WebSiteFactory();
WebSite fx = f.GetWebSiteCategory("产品展示");
fx.Use(new User("小菜"));
WebSite fy = f.GetWebSiteCategory("产品展示");
fy.Use(new User("小白"));
WebSite f1 = f.GetWebSiteCategory("博客");
f1.Use(new User("小黑"));
WebSite f2 = f.GetWebSiteCategory("博客");
f2.Use(new User("小绿"));
Console.Read();
}
如果一个应用程序使用了大量的对象,而大量哒这些对象造成了很大的储存开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。
在使用UITableView的时候我们应该熟悉这样的接口:
在要使用一个Cell的时候我们先去看看tableView中有没有可以重用的cell,如果有就用这个可以重用的cell,只有在没有的时候才去创建一个Cell。这就是享元模式。
享元模式可以理解成,当细粒度的对象数量特别多的时候运行的代价会相当大,此时运用共享的技术来大大降低运行成本。比较突出的表现就是内容有效的抑制内存抖动的情况发生,还有控制内存增长。它的英文名字是flyweight,让重量飞起来。哈哈。名副其实,在一个TableView中Cell是一个可重复使用的元素,而且往往需要布局的cell数量很大。如果每次使用都创建一个Cell对象,系统的内容抖动会非常明显,而且系统的内存消耗也是比较大的。突然一想,享元模式只是给对象实例共享提供了一个比较霸道的名字吧。
- (DZTableViewCell*) dzTableView:(DZTableView *)tableView cellAtRow:(NSInteger)row
{
static NSString* const cellIdentifiy = @"detifail";
DZTypeCell* cell = (DZTypeCell*)[tableView dequeueDZTalbeViewCellForIdentifiy:cellIdentifiy];
if (!cell) {
cell = [[DZTypeCell alloc] initWithIdentifiy:cellIdentifiy];
}
NSString* text = _timeTypes[row];