大话设计模式-享元模式
享元模式
运营共享技术有效地支持大量细粒度的对象。
享元模式的原理
享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类的实例来表示数据。
如果能发现这些实例除了几个参数外基本都是相通的,有时就能够大幅地减少需要实例化的类的数量。
如果能把那些参数移到类的实例的外面,在方法调用时将他们传递进来,就可以通过共享大幅地减少单个实例的数目。
我的理解是原来一个对象的实例,它的字段和属性占用100KB,那么100个对象就是占用了100*100KB内存,现在把不变的提炼出来共享,比如字段和属性中由50KB是不变的,那100个对象就是占用了100*50KB(变的)+50KB(不变的)的内存。
占用内存=外部信息大小*外部信息实例数量+内部信息大小*内部信息实例数量
维护一个键值对,外部信息的某个字段作为键,内部信息实例作为值,这样就做到了共享内部信息。
享元模式的使用时机
如果一个应用程序使用了大量的对象,而大量的对象造成了很大的存储开销。
对象的大多数状态是外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
享元模式结构演示
用户
public class User { public string Name { get; private set; } public User(string name) => Name = 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 { 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() => flyweights.Count; }
测试结果
//网站工厂 WebSiteFactory f = new WebSiteFactory(); //声明两个论坛 WebSite fx = f.GetWebSiteCategory("论坛"); fx.Use(new User("路人甲")); WebSite fy = f.GetWebSiteCategory("论坛"); fy.Use(new User("路人乙")); //声明两个博客 WebSite fi = f.GetWebSiteCategory("博客"); fi.Use(new User("路人A")); WebSite fj = f.GetWebSiteCategory("博客"); fj.Use(new User("路人B")); //打印网站种类数量 Console.WriteLine($"网站的种类数量为:{f.GetWebsiteCount()}"); //测试结果 网站分类:论坛 用户:路人甲 网站分类:论坛 用户:路人乙 网站分类:博客 用户:路人A 网站分类:博客 用户:路人B 网站的种类数量为:2