今天我们来讲一下享元模式。
我们在工作之余可能会接一些私活,比如,帮人开发一个网站,帮人开发一个私人博客。随着私活的增多,会发现,有很多项目是有相同之处的,比如,帮人开发一个网站,你会发现,之前做的一些网站的代码单元是可以公共的。所以,即便是有很多的私活,我们不要盲目的去做一些项目,我们要善于发现,善于总结,这样会大大提高我们的效率。
我们将上述场景用代码体现一下就如同下面代码:
1 /// <summary> 2 /// 网站类 3 /// </summary> 4 class WebSite 5 { 6 private string name = ""; 7 8 public WebSite(string name) 9 { 10 this.name = name; 11 } 12 13 public void Use() 14 { 15 Console.WriteLine($"网站分类:{name}"); 16 } 17 }
客户端调用:
1 public static void Main() 2 { 3 WebSite fx = new WebSite("门户网站"); 4 fx.Use(); 5 6 WebSite fy = new WebSite("门户网站"); 7 fy.Use(); 8 9 WebSite fz = new WebSite("门户网站"); 10 fz.Use(); 11 12 WebSite fl = new WebSite("个人博客"); 13 fl.Use(); 14 15 WebSite fm = new WebSite("个人博客"); 16 fm.Use(); 17 18 WebSite fn = new WebSite("个人博客"); 19 fn.Use(); 20 21 Console.ReadKey(); 22 }
在弄清楚如何共享代码之前,我们先来谈一下今天我们要讲的设计模式——享元模式。
享元模式,运用共享技术有效地支持大量细粒度地对象,所有具体享元类地超类或接口,通过这个接口,可以接受并作用于外部状态。
我们再来看一下它的结构代码:
1 //所有具体享元类地超类或接口,通过这个接口,可以接受并作用于外部状态 2 abstract class Flyweight 3 { 4 public abstract void Operation(int extrinsicstate); 5 } 6 //继承Flyweight实现Flyweight接口 7 class ConcreteFlyweight : Flyweight 8 { 9 public override void Operation(int extrinsicstate) 10 { 11 Console.WriteLine($"具体Flyweight:{extrinsicstate}"); 12 } 13 } 14 //不需要共享Flyweight子类,因为Flyweight接口共享成为可能,但它并不强制共享 15 class UnsharedConcreteFlyweight : Flyweight 16 { 17 public override void Operation(int extrinsicstate) 18 { 19 Console.WriteLine($"不共享的具体Flyweight:{extrinsicstate}"); 20 } 21 } 22 //享元工厂,用来创建并管理Flyweight对象,它主要是用来确保合理的 23 //共享Flyweight,当用户请求一个Flyweight时,享元工厂对象提供一个 24 //已经创建的实例或者创建一个(如果不存在的话) 25 class FlyweighFactory 26 { 27 private Hashtable flyweights = new Hashtable(); 28 /// <summary> 29 /// 初始化工厂时,先生成三个实例 30 /// </summary> 31 public FlyweighFactory() 32 { 33 flyweights.Add("X", new ConcreteFlyweight()); 34 flyweights.Add("Y", new ConcreteFlyweight()); 35 flyweights.Add("Z", new ConcreteFlyweight()); 36 } 37 //根据客户端请求,获得已生成的实例 38 public Flyweight GetFlyweight(string key) 39 { 40 return ((Flyweight) flyweights[key]); 41 } 42 }
客户端:
1 public static void Main() 2 { 3 //代码外部状态 4 int extrinsicstate = 22; 5 FlyweighFactory f = new FlyweighFactory(); 6 7 Flyweight fx = f.GetFlyweight("X"); 8 fx.Operation(--extrinsicstate); 9 10 Flyweight fy = f.GetFlyweight("Y"); 11 fy.Operation(--extrinsicstate); 12 13 Flyweight fz = f.GetFlyweight("Z"); 14 fz.Operation(--extrinsicstate); 15 16 UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight(); 17 18 uf.Operation(--extrinsicstate); 19 20 Console.ReadKey(); 21 }
好,我们用享元模式将我们案例中的代码来重构一下:
1 //网站抽象类 2 abstract class WebSite 3 { 4 public abstract void Use(); 5 } 6 //具体网站类 7 class ConcreteWebSite : WebSite 8 { 9 private string name = ""; 10 11 public ConcreteWebSite(string name) 12 { 13 this.name = name; 14 } 15 public override void Use() 16 { 17 Console.WriteLine($"网站分类{name}"); 18 } 19 } 20 //网站工厂 21 class WebSiteFactory 22 { 23 private Hashtable flyweights = new Hashtable(); 24 25 public WebSite GetWebSiteCategory(string key) 26 { 27 //判断是否存在这个对象,如果存在,则直接返回,否则实例化它再返回 28 if (!flyweights.ContainsKey(key)) 29 { 30 flyweights.Add(key, new ConcreteWebSite(key)); 31 return (WebSite)flyweights[key]; 32 } 33 else 34 { 35 return (WebSite)flyweights[key]; 36 } 37 } 38 //获得网站分类总数 39 public int GetWebSiteCount() 40 { 41 return flyweights.Count; 42 } 43 }
客户端:
1 public static void Main() 2 { 3 WebSiteFactory f = new WebSiteFactory(); 4 5 //实例化 门户网站 对象 6 WebSite fx = f.GetWebSiteCategory("门户网站"); 7 fx.Use(); 8 9 //共享上方生成的对象,不再实例化 10 WebSite fy = f.GetWebSiteCategory("门户网站"); 11 fy.Use(); 12 //共享上方生成的对象,不再实例化 13 WebSite fz = f.GetWebSiteCategory("门户网站"); 14 fz.Use(); 15 16 WebSite fl = f.GetWebSiteCategory("个人博客"); 17 fl.Use(); 18 19 WebSite fm = f.GetWebSiteCategory("个人博客"); 20 fm.Use(); 21 22 WebSite fn = f.GetWebSiteCategory("个人博客"); 23 fn.Use(); 24 25 //统计实例化个数,结果应该为2 26 Console.WriteLine($"网站分类总数为{f.GetWebSiteCount()}"); 27 Console.ReadKey(); 28 }
这样写基本体现了享元模式享元模式,但是我们在做项目的过程中,即便是再相似的项目,面对不同企业,也会有不同的地方。
好,今天的享元模式就讲到这里了,下一篇我们讲 解释器模式
本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持