首页 > 代码库 > 设计模式(15)---享元模式

设计模式(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();        }    }
View Code

运行结果:

 

三、具体实例:

构建一个由不同用户使用的通用网站,具体代码如下:

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());
View Code

 

四、优缺点及适用场景

优点:

降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。

缺点:

1)为了使对象可以共享,需要将对象的一些状态外部化,增加了系统复杂度

2)将享元对象状态外部化,使得读取外部状态的运行时间稍微变长。

 

适用场景:

系统中需要大量的细粒度对象,同时这些对象耗费大量的内存,并且对象的状态大部分可以外部化,此时使用享元模式是没有错的。

 

设计模式(15)---享元模式