设计模式(15)---享元模式
一、定义
享元模式:运用共享技术有效地支持大量细粒度的对象。
解释:需要大量重复new一个对象时,使用享元模式可以让你减少对象的初始化,从而减小内存开销。太苍白了,理解的不到位,希望自己以后补充吧。
补充:当一个对象的状态可在外部初始化,同时系统中需要大量重复创建该对象时,享元模式在创建对象的工厂方法中使用一个哈希表,用于保存其外部化状态和对象本身。在系统中,使用对象时首先判断其是否存在,存在则拿来直接使用,不存在需要重新创建并保存到哈希表中。
二、UML类图及基本代码
基本代码:
public abstract class Flyweight { public abstract void Operation(int extrinsicstate); } public class ConcreteFlyweight : Flyweight { // 内部状态 private string intrinsicstate; // 构造函数 public ConcreteFlyweight(string innerState) { this.intrinsicstate = innerState; } /// <summary> /// 享元类的实例方法 /// </summary> /// <param name="extrinsicstate">外部状态</param> public override void Operation(int extrinsicstate) { Console.WriteLine("具体实现类: intrinsicstate {0}, extrinsicstate {1}", intrinsicstate, extrinsicstate); } } public class FlyweightFactory { // 最好使用泛型Dictionary<string,Flyweighy> //public Dictionary<string, Flyweight> flyweights = new Dictionary<string, Flyweight>(); public Hashtable flyweights = new Hashtable(); public FlyweightFactory() { flyweights.Add("A", new ConcreteFlyweight("A")); flyweights.Add("B", new ConcreteFlyweight("B")); flyweights.Add("C", new ConcreteFlyweight("C")); } public Flyweight GetFlyweight(string key) { // 更好的实现如下 //Flyweight flyweight = flyweights[key] as Flyweight; //if (flyweight == null) //{ // Console.WriteLine("驻留池中不存在字符串" + key); // flyweight = new ConcreteFlyweight(key); //} //return flyweight; return flyweights[key] as Flyweight; } }
客户端调用:
class Program { static void Main(string[] args) { // 定义外部状态,例如字母的位置等信息 int externalstate = 10; // 初始化享元工厂 FlyweightFactory factory = new FlyweightFactory(); // 判断是否已经创建了字母A,如果已经创建就直接使用创建的对象A Flyweight fa = factory.GetFlyweight("A"); if (fa != null) { // 把外部状态作为享元对象的方法调用参数 fa.Operation(--externalstate); } // 判断是否已经创建了字母B Flyweight fb = factory.GetFlyweight("B"); if (fb != null) { fb.Operation(--externalstate); } // 判断是否已经创建了字母D Flyweight fd = factory.GetFlyweight("D"); if (fd != null) { fd.Operation(--externalstate); } else { Console.WriteLine("驻留池中不存在字符串D"); // 这时候就需要创建一个对象并放入驻留池中 ConcreteFlyweight d = new ConcreteFlyweight("D"); factory.flyweights.Add("D", d); } Console.Read(); } }
运行结果:
三、具体实例:
构建一个由不同用户使用的通用网站,具体代码如下:
public class User { private string name; public string Name { get { return name; } } public User(string name) { this.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("website type:" + name + "user:" + 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; } }
客户端调用:
WebsiteFactory wf = new WebsiteFactory(); Website wx = wf.GetWebsiteCategory("show"); wx.Use(new User("a")); Website wy = wf.GetWebsiteCategory("show"); wy.Use(new User("b")); Website wz = wf.GetWebsiteCategory("see"); wz.Use(new User("c")); Console.WriteLine("website type num:" + wf.GetWebsiteCount());
四、优缺点及适用场景
优点:
降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
缺点:
1)为了使对象可以共享,需要将对象的一些状态外部化,增加了系统复杂度
2)将享元对象状态外部化,使得读取外部状态的运行时间稍微变长。
适用场景:
系统中需要大量的细粒度对象,同时这些对象耗费大量的内存,并且对象的状态大部分可以外部化,此时使用享元模式是没有错的。
最新博客信息,请关注“小项目笔记”公众号;