设计模式之---享元模式

享元模式(Flyweight),运用共享技术有效的支持大量细粒度的对象。

什么时候使用享元模式

如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就可以考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。

归纳享元模式的好处?

用了享元模式,所以有了共享对象,实例总数就打打减少了,如果共享的对象越多,存储节约的也就越多,节约量随着共享状态的增多而增多。

            string titlea = "yxz";
            string titleb = "yxz";
            Console.WriteLine(object.ReferenceEquals(titleb, titlea));

基本代码如下:

客户端代码

            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);

            Flyweight uf = new UnsharedConcreteFlyweight();
            uf.Operation(--extrinsicstate);

            Console.Read();
View Code

后台

    abstract class Flyweight
    {
        public abstract void Operation(int extrinsicsstate);
    }
    class ConcreteFlyweight : Flyweight
    {
        public override void Operation(int extrinsicsstate)
        {
            Console.WriteLine("具体Flyweight:" + extrinsicsstate);
        }
    }

    class UnsharedConcreteFlyweight : Flyweight
    {
        public override void Operation(int extrinsicsstate)
        {
            Console.WriteLine("不共享的具体Flyweight:" + extrinsicsstate);
        }
    }
    class FlyweightFactory                                                  //享元工厂,用来创建并管理Flyweight对象。它主要用来确保合理的共享Flyweight
    {
        private Hashtable flyweight = new Hashtable();
        public FlyweightFactory()                                           //初始化工厂时,先生成三个实例
        {
            flyweight.Add("X", new ConcreteFlyweight());
            flyweight.Add("Y", new ConcreteFlyweight());
            flyweight.Add("Z", new ConcreteFlyweight());
        }
        public Flyweight GetFlyweight(string key)                           //根据客户端请求,获得已生成的实例
        {
            return ((Flyweight)flyweight[key]);
        }
    }
View Code

UML类图

 

 内部状态和外部状态

在享元对象内部并且不会随环境改变而改变的共享部分,称为享元对象的内部状态。随着环境改变而改变的,不可以共享的状态就是外部状态了。

享元模式可以避免大量非常相似类的开销。

在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了参数外基本都是相同的,有时就能够大幅度的减少需要实例化的类的数量。如果能把那些参数转移到类实例的外面,在方法调用时将它们传递进来,就可以共享大幅度的减少单个实例的数目。

 

            WebSiteFactory f = new WebSiteFactory();
            WebSite fx = f.GetWebsiteCategory("产品展示");
            fx.Use(new User("小菜"));

            WebSite fy = f.GetWebsiteCategory("产品展示");
            fx.Use(new User("大鸟"));

            WebSite fz = f.GetWebsiteCategory("产品展示");
            fx.Use(new User("小鸟"));
            WebSite fr = f.GetWebsiteCategory("产品");
            fx.Use(new User("小鸟"));
            Console.WriteLine("得到网站的分类总数:{0}", f.GetWebSiteCount());

            Console.Read();
View Code
    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 = string.Empty;
        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;
        }
    }
View Code

 

posted @ 2021-10-05 19:17  HelloWorld庄先生  阅读(36)  评论(0编辑  收藏  举报