模式定义
享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。
目的:解决多次创建(大)对象引起的性能问题。
术语
- 内部状态:存储在享元对象内部并且不会随环境改变而改变的状态,因此内部状态可以共享。
- 外部状态是随环境改变而改变的、不可以共享的状态。
享元对象的外部状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。
UML类图
- 抽象享元类 Flyweight 享元类接口,通过它可以接受并作用于外部状态
- 具体享元类 ConcreteFlyweight 实现了抽象享元接口,实例称为享元对象(被多次复用的对象,客户端通过享元工厂创建);
- 非共享具体享元类 UnsharedConcreteFlyweight 不能被共享的抽象享元类的子类(客户端直接new该对象)
- 享元工厂类 FlyweightFactory 用于创建并管理享元对象,它针对抽象享元类编程,将各种类型的具体享元对象存储在一个享元池中。
根据业务直接从享元池中获取享元类对象,或创建新的享元类添加到享元池
代码结构
public static class FlyweightApp
{
public static void Run()
{
int extrinsicstate = 22;
FlyweightFactory factory = new FlyweightFactory();
// Work with different flyweight instances
Flyweight fx = factory.GetFlyweight("X");
fx.Operation(--extrinsicstate);
Flyweight fy = factory.GetFlyweight("Y");
fy.Operation(--extrinsicstate);
Flyweight fz = factory.GetFlyweight("Y");
fz.Operation(--extrinsicstate);
UnsharedConcreteFlyweight fu = new UnsharedConcreteFlyweight();
fu.Operation(--extrinsicstate);
}
}
public abstract class Flyweight
{
public abstract void Operation(int extrinsicstate);
}
public class ConcreteFlyweight : Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("ConcreteFlyweight: " + extrinsicstate);
}
}
public class UnsharedConcreteFlyweight : Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("Unshared ConcreteFlyweight: " + extrinsicstate);
}
}
public class FlyweightFactory
{
private Hashtable flyweights = new Hashtable();
public FlyweightFactory()
{
flyweights.Add("X", new ConcreteFlyweight());
flyweights.Add("Y", new ConcreteFlyweight());
flyweights.Add("Z", new ConcreteFlyweight());
}
public Flyweight GetFlyweight(string key)
{
return ((Flyweight)flyweights[key]);
}
}
情景模式
一服装店聘请一个男模和一个女模试穿衣服(请多了服装店付不起钱),但是有很多衣服需要试穿。
public static class FlyweightApp
{
public static void Run()
{
List<string> maleCloths = new List<string>() { "男鞋", "短裤", "衬衫" };
List<string> femaleCloths = new List<string>() { "超短裤", "齐逼小短裙", "肉色袜裤" };
ModelFactory modelFactory = new ModelFactory();
Model male = modelFactory.GetFlyweight(Gender.male);
Model female = modelFactory.GetFlyweight(Gender.female);
foreach (string item in maleCloths)
{
male.Display(item);
}
foreach (string item in femaleCloths)
{
female.Display(item);
}
}
}
public enum Gender
{
male, female
}
public abstract class Model
{
public abstract void Display(string cloth);
}
public class MaleModel : Model
{
public override void Display(string cloth)
{
Console.WriteLine("我是帅气的男模,我穿的是{0}", cloth);
}
}
public class FemaleModel : Model
{
public override void Display(string cloth)
{
Console.WriteLine("我是骚气的女模,我穿的是{0}", cloth);
}
}
public class ModelFactory
{
private Hashtable flyweights = new Hashtable();
public ModelFactory()
{
flyweights.Add(Gender.male, new MaleModel());
flyweights.Add(Gender.female, new MaleModel());
}
public Model GetFlyweight(Gender key)
{
return ((Model)flyweights[key]);
}
}