项目多也别傻做 享元模式
26.1 项目多也别傻做
namespace 享元模式 { class Program { static void Main(string[] args) { WebSite fx = new WebSite("产品展示"); fx.Use(); WebSite fy = new WebSite("产品展示"); fy.Use(); WebSite fz = new WebSite("产品展示"); fz.Use(); WebSite fl = new WebSite("博客"); fl.Use(); WebSite fm = new WebSite("博客"); fm.Use(); WebSite fn = new WebSite("博客"); fn.Use(); Console.Read(); } } //网站, class WebSite { private string name = ""; public WebSite(string name) { this.name = name; } public void Use() { Console.WriteLine("网站分类:" + name); } } }
如果要做三个产品展示,三个博客的网站,就需要六个网站类的实例,而其实它们本质上都是一样的代码,如果网站增多,实例也就随着增多,这对服务器的资源浪费的很严重,
26.2 享元模式
运用共享技术有效的支持大量细粒度的对象,
namespace 享元模式 { class Program { static void Main(string[] args) { 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); UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight(); uf.Operation(--extrinsicstate); Console.Read(); } } //是所有具体享元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态, abstract class Flyweight { public abstract void Operation(int extrinsicstate); } //是继承Flyweight超类或实现Flyweight接口,并为内部状态增加存储空间, class ConcreteFlyweight : Flyweight { public override void Operation(int extrinsicstate) { Console.WriteLine("具体Flyweight:" + extrinsicstate); } } //是指那些不需要共享的Flyweight子类,因为Flyweight接口共享成为可能,但它并不强制共享, class UnsharedConcreteFlyweight : Flyweight { public override void Operation(int extrinsicstate) { Console.WriteLine("不共享的具体Flyweight:" + extrinsicstate); } } //是享元工厂,用来创建并管理Flyweight对象, //主要是用来确保合理的共享Flyweight,当用户请求一个Flyweight时, //FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话), 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]); } } }
26.3 网站共享代码
namespace 享元模式 { class Program { static void Main(string[] args) { WebSiteFactory f = new WebSiteFactory(); WebSite fx = f.GetWebSiteCategory("产品展示"); //实例化产品展示的网站的对象, fx.Use(); WebSite fy = f.GetWebSiteCategory("产品展示"); //共享上方生成的对象,不在实例化, fy.Use(); WebSite fz = f.GetWebSiteCategory("产品展示"); fz.Use(); WebSite fl = f.GetWebSiteCategory("博客"); fl.Use(); WebSite fm = f.GetWebSiteCategory("博客"); fm.Use(); WebSite fn = f.GetWebSiteCategory("博客"); fn.Use(); Console.WriteLine("网站分类总数为 {0}", f.GetWebSiteCount()); Console.Read(); } } //抽象的网站, abstract class WebSite { public abstract void Use(); } //具体的网站, class ConcreteWebSite : WebSite { private string name = ""; public ConcreteWebSite(string name) { this.name = name; } public override void Use() { Console.WriteLine("网站分类:" + name); } } //网站工厂, class WebSiteFactory { private Hashtable flyweights = new Hashtable(); //获得网站分类, public WebSite GetWebSiteCategory(string key) { if (!flyweights.ContainsKey(key)) //判断是否存在这个对象,如果存在,则直接返回,若不存在,则实例化它在返回, flyweights.Add(key, new ConcreteWebSite(key)); return ((WebSite)flyweights[key]); } //获得网站分类总数, public int GetWebSiteCount() { return flyweights.Count; //得到实例的个数, } } }
没有体现对象间的不同,只体现了它们共享的部分,
26.4 内部状态与外部状态
在享元对象内部并且不会随环境改变而改变的共享部分,可以称为是享元对象的内部状态,而随环境改变而改变的,不可以共享的状态就是外部状态了,事实上,享元模式可以避免大量非常相似类的开销,在程序设计中,有时需要生成大量细粒度的类实例来表示数据,如果能发现这些实例除了几个参数外基本都是相同的,有时就能够受大幅度的减少需要实例化的类的数量,如果能把那些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度的减少单个实例的数目,
namespace 享元模式 { class Program { static void Main(string[] args) { WebSiteFactory f = new WebSiteFactory(); WebSite fx = f.GetWebSiteCategory("产品展示"); fx.Use(new User("小菜")); WebSite fy = f.GetWebSiteCategory("产品展示"); fy.Use(new User("大鸟")); WebSite fz = f.GetWebSiteCategory("产品展示"); fz.Use(new User("娇娇")); WebSite fl = f.GetWebSiteCategory("博客"); fl.Use(new User("老顽童")); WebSite fm = f.GetWebSiteCategory("博客"); fm.Use(new User("桃谷六仙")); WebSite fn = f.GetWebSiteCategory("博客"); fn.Use(new User("南海鳄神")); Console.WriteLine("得到网站分类总数为 {0}", f.GetWebSiteCount()); string titleA = "大话设计模式"; string titleB = "大话设计模式"; Console.WriteLine(Object.ReferenceEquals(titleA, titleB)); Console.Read(); } } //用户类, public class User { private string name; public User(string name) { this.name = name; } public string Name { get { return name; } } } //抽象的网站, abstract class WebSite { public abstract void Use(User user); } //具体的网站, class ConcreteWebSite : WebSite { private string name = ""; public ConcreteWebSite(string name) { this.name = name; } public override void Use(User user) { Console.WriteLine("网站分类:" + name + " 用户:" + user.Name); } } //网站工厂, class WebSiteFactory { private Hashtable flyweights = new Hashtable(); //获得网站分类, public WebSite GetWebSiteCategory(string key) { if (!flyweights.ContainsKey(key)) flyweights.Add(key, new ConcreteWebSite(key)); return ((WebSite)flyweights[key]); } //获得网站分类总数, public int GetWebSiteCount() { return flyweights.Count; } } }
26.5 享元模式应用
如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用,还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式,