运用共享技术有效的支持大量细粒度的对象。
//是所有具体享元类的超类或接口,通过这个接口,fliweight可以接收并作用于外部状态
abstractclass Flyweight
{
//参数为代码的外部状态,子类可以根据外部状态发生变化
public abstract void Operation(int extrinsicstate);
};
class ConcretFlyweight : Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("ConcretFlyweight :" +extrinsicstate);
}
};
//这里是指不需要共享的Flyweight子类,因为Flyweight接口共享成为可能,但他不强制共享,用来解决不需要共享的对象的问题
class UnsharedConcretFlyweight :Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("UnsharedConcret Flyweight :" + extrinsicstate);
}
};
//这是一个享元工厂,用来创建并管理Flyweight对象。主要用来确保合理的共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个
class FlyweightFactory
{
private Hashtable flyweights = new Hashtable();
//我们也并非一定要在构造函数中就初始化几个对象
public FlyweightFactory()
{
flyweights.Add("X", new ConcretFlyweight());
flyweights.Add("Y", new ConcretFlyweight());
flyweights.Add("Z", new ConcretFlyweight());
}
public Flyweight GetFlyweight(string key)
{
return((Flyweight)flyweights[key]);
}
};
void main()
{
int extrinsicstate = 22;
FlyweightFactory f = new FlyweightFactory();
Flyweight fx = f.GetFlyweight("X");
fx.Operation(--extrinsicstate);
Flyweight fy = f.GetFlyweight("Y");
fy.Operation(--extrinsicstate);
Flyweight fz = f.GetFlyweight("Z");
fz.Operation(--extrinsicstate);
UnsharedConcretFlyweight uf = new UnsharedConcretFlyweight();
uf.Operation(--extrinsicstate);
}
在享元对象内部并且不会随环境改变而改变的共享部分,可以称为享元对象的内部状态,而随环境改变的、不可共享的状态就是外部状态
享元模式可以避免大量非常相似的开销。
在程序设计中,有时需要设计大量细粒度的类实例来表示数据,如果发现这些实例除了几个参数外基本上是相同的,有时就可以大幅度的减少需要实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时将他们传递进来,就可以通过共享大幅度的减少单个实例的数目。
书上给出的例子是:
几个建网站的需求,网站虽然不同,但内部实现却相似
//是网站类的外部状态 , 网站的客户账号
public class User
{
private string name;
public User(string name)
{
this.name = name;
}
public string Name
{
get{ return name; }
}
};
//网站抽象类
abstractclass Website
{
public abstract void Use(User user);
};
//具体网站类
class ConcretWebsite :Website
{
private string name = "";
public ConcretWebsite(string name)
{
this.name = name;
}
public override void Use(User user)
{
Console.WriteLine("网站分类: " + name + "用户:" + user.Name);
}
};
//网站工厂
class WebsiteFactory
{
private Hashtable fws = new Hashtable();
//获得网站分类
public Website GetWebsiteCategory(string key)
{
if (!fws.ContainsKey(key))
fws.Add(key, new ConcretWebsite(key));
return fws[key];
}
};
void main()
{
WebsiteFactory f = new WebsiteFactory();
Website fx = f.GetWebsiteCategory("产品展示");
fx.Use("xiaoming");
Website fy = f.GetWebsiteCategory("博客");
fx.Use("xiaohong");
//..
}
如果一个程序使用了大量的对象,而大量的这些对象造成了很大的存储开销就应该考虑使用这种模式
使用了享元模式,就有了共享对象,实例总数就大大减少
比如在.NET中,
String A = “hello”;
String B = “hello”;
Console.WriteLine(Object.ReferenceEquals(A,B));
得到的返回值就是true,表明他们两个共享一个对象。这就是用到了享元模式