设计模式(二十二)享元模式
享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本都是相同的,有时就能够受大幅度地减少需要实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。
应用场景
1、如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销是就应该考虑使用;
2、对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。
实际上在.NET中的字符串 string 就是运用 Flyweight 模式。

基本代码
1 // Flyweight 类是所有具体享元类的超类或接口,通过这个接口,Flyweight 可以接受并作用于外部状态 2 abstract class Flyweight 3 { 4 // 5 public abstract void Operation(int extrinsicstate); 6 } 7 8 // ConcreteFlyweight 是继承 Flyweight 超类或实现 Flyweight 接口,并未内部状态增加存储空间 9 class ConcreteFlyweight : Flyweight 10 { 11 public override void Operation(int extrinsicstate); 12 { 13 Console.WriteLine("具体 Flyweight:" + extrinsicstate); 14 } 15 } 16 17 // UnsharedConcreteFlyweight 是指那些不需要共享的 Flyweight 子类。 18 class UnsharedConcreteFlyweight : Flyweight 19 { 20 public override void Operation(int extrinsicstate); 21 { 22 Console.WriteLine("不共享的具体 Flyweight:" + extrinsicstate); 23 } 24 } 25 26 // FlyweightFactory 是一个享元工厂,用来创建并管理 Flyweight 对象。它主要是用来确保合理地共享 Flyweight , 当用户请求一个 Flyweight 时, 27 // FlyweightFactory 对象提供一个已创建的实例或者创建一个(如果不存在的话)。 28 class FlyweightFactory 29 { 30 private Hashtable flyweights = new Hashtable(); 31 32 public FlyweightFactory() 33 { 34 flyweights.Add("X", new ConcreteFlyweight()); 35 flyweights.Add("Y", new ConcreteFlyweight()); 36 flyweights.Add("Z", new ConcreteFlyweight()); 37 } 38 39 // 根据客户端请求,获得已生成的实例 40 public Flyweight GetFlyweight(string key) 41 { 42 return ((Flyweight)flyweights[key]); 43 } 44 } 45 46 // 客户端 47 static void Main(string[] args) 48 { 49 // 代码外部状态 50 int extrinsicstate = 22; 51 52 FlyweightFactory f = new FlyweightFactory(); 53 54 Flyweight fx = f.GetFlyweight("X"); 55 fx.Operation(--extrinsicstate); 56 57 Flyweight fy = f.GetFlyweight("Y"); 58 fy.Operation(--extrinsicstate); 59 60 Flyweight fz = f.GetFlyweight("Z"); 61 fz.Operation(--extrinsicstate); 62 63 UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight(); 64 uf.Operation(--extrinsicstate); 65 66 Console.Read(); 67 }
【例】网站共享代码

基本代码
1 // 用户类 2 public class User 3 { 4 private string name; 5 public User(string name) 6 { 7 this.name = name; 8 } 9 10 public string Name 11 { 12 get { return name; } 13 } 14 } 15 16 // 网站抽象类 17 abstract class Website 18 { 19 // Use 方法需要传递 User 对象 20 public abstract void Use(User user); 21 } 22 23 // 具体网站类 24 class ConcreteWebSite : Website 25 { 26 private string name = " "; 27 public ConcreteWebSite(string name) 28 { 29 this.name = name; 30 } 31 public override void Use(User user) 32 { 33 Console.WriteLine("网站分类:" + name + “用户:” + user.Name); 34 } 35 } 36 37 // 网站工厂类 38 class WebSiteFacory 39 { 40 private Hashtable flyweights = new Hashtable(); 41 42 // 获得网站分类 43 public WebSite GetWebSiteCategory(string key) 44 { 45 // 判断是否存在这个对象,如果存在,则直接返回,若不存在,则实例化后再返回 46 if(!flyweights.ContainsKey(key)) 47 flyweights.Add(key, new ConcreteWebSite(key)); 48 return ((WebSite)flyweights[key]); 49 } 50 51 // 获得网站分类总数,得到实例的个数 52 public int GetWebSiteCount() 53 { 54 return flyweights.Count; 55 } 56 } 57 58 // 客户端 59 static void Main(string[] args) 60 { 61 WebSiteFactory f = new WebSiteFactory(); 62 63 WebSite fx = f.GetWebSiteCategory("产品展示"); 64 fx.Use(new User("1")); 65 66 WebSite fy = f.GetWebSiteCategory("产品展示"); 67 fy.Use(new User("2")); 68 69 WebSite fz = f.GetWebSiteCategory("产品展示"); 70 fz.Use(new User("3")); 71 72 WebSite fl = f.GetWebSiteCategory("博客"); 73 fl.Use(new User("4")); 74 75 WebSite fm = f.GetWebSiteCategory("博客"); 76 fm.Use(new User("5")); 77 78 WebSite fn = f.GetWebSiteCategory("博客"); 79 fn.Use(new User("6")); 80 81 Console.WriteLine("网站分类总数为:{0}", f.GetWebSiteCount); 82 83 Console.Read(); 84 }

浙公网安备 33010602011771号