初尝Flyweight 模式
面向对象很好的解决了抽象的问题,在大多数的情况下也不会影响到系统性能。但,当对象的数量级达到一定的时候,过多的对象会给系统内存带来难以承受的开销。比如文字处理中的字符。
Flyweight在牛津字典中的解释是”boxer of the lightest class”。(意思是轻量级拳击手)。在这里其实应该是取”the lightest class”这部份的解释,一个特轻量级类别,这个类别所产生的对象可以共用在每一个场合(context),并依场合表现其外蕴。这里根据其具体表达形式,翻译为享元模式。
享元模式以共享的方式高效地支持大量的细粒度对象。享元对象能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(External State)。内蕴状态是存储在享元对象内部并且不会随环境改变而改变。因此内蕴状态并可以共享。
外蕴状态是随环境改变而改变的、不可以共享的状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态与内蕴状态是相互独立的。
意图:
运用共享技术有效地支持大量细粒度的对象。
单纯享元模式结构图:
复合享元模式结构图:
其中尤其需要指出的是FlyweightFactory 这个角色:负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象请求一个享元对象的时候,享元工厂角色需要检查系统中是否已经有一个符合要求的享元对象,如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个新的合适的享元对象。
一段代码:
using System;
using System.Collections;
namespace Flyweight
{
public class CoffeeServer
{
private string flavor;//内蕴状态(Internal State)
public CoffeeServer(string flavor)
{
this.flavor = flavor;
}
public void Serve(Table table)
{
Console.WriteLine("Table {0} Getting flavor {1}!", table.Number, this.flavor);
}
}
public class CoffeeFactory
{
public Hashtable coffees = new Hashtable();
public CoffeeServer GetCoffee(string key)
{
if (!coffees.Contains(key))
coffees.Add(key, new CoffeeServer(key));
return (CoffeeServer)coffees[key];
}
public int GetTotalNum()
{
return coffees.Count;
}
}
//外蕴状态 (External State)
public class Table
{
private int number;
public Table(int number)
{
this.number = number;
}
public int Number
{
get
{
return this.number;
}
}
}
class Program
{
static int OrderNum = 0;
static CoffeeFactory factory = new CoffeeFactory();
static void Main(string[] args)
{
//发出7个订单,但实际上只使用了4种咖啡
Order("Black Coffee");
Order("Black Coffee");
Order("Cappuccino");
Order("Cappuccino");
Order("Cappuccino");
Order("Espresso");
Order("Coffee");
Console.WriteLine("Order Number :{0}", OrderNum);
Console.WriteLine("Coffee Number :{0}", factory.GetTotalNum());
}
public static void Order(string flavor)
{
CoffeeServer coffee = factory.GetCoffee(flavor);
coffee.Serve(new Table(OrderNum));
OrderNum++;
}
}
}
运行截图:



近期评论