项目多也别傻做 享元模式

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

}
View Code

如果要做三个产品展示,三个博客的网站,就需要六个网站类的实例,而其实它们本质上都是一样的代码,如果网站增多,实例也就随着增多,这对服务器的资源浪费的很严重,

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

}
View Code

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;                                          //得到实例的个数,
        }
    }

}
View Code

没有体现对象间的不同,只体现了它们共享的部分,

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

}
View Code

26.5 享元模式应用

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

posted @ 2019-08-08 11:07  _Huang95  阅读(293)  评论(0编辑  收藏  举报