设计模式之-享元模式

定义:

享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。系统只使用少许的对象,而这些对象都很类似,状态变化很小,能够实现对象的屡次复用。因为享元模式要求可以共享的对象必须是细粒度对象,所以它又称为轻量级模式,它是一种对象结构型模式。git

享元模式参与者

  • Flyweight:全部具体享元类的超类或接口,经过这个超类或接口,Flyweight能够接受并做用于外部状态。
  • FlyweightFactory:享元工厂,用来建立并管理Flyweight,当用户请求一个Flyweight时,FlyweightFactory提供一个已建立的实例或者建立一个(若是不存在)。
  • ConcreteFlyweight:继承Flyweight超类或实现Flyweight接口。
  • UnsharedConcreteFlyweight:指那些不须要共享的Flyweight子类。

享元模式基本代码

Flyweight类:github

namespace FlyweightPattern.BasicStructure
{
    abstract class Flyweight
    {
        public abstract void Operation(int extrinsicState);
    }
}

ConcreteFlyweight类:web

namespace FlyweightPattern.BasicStructure
{
    class ConcreteFlyweight : Flyweight
    {
        public override void Operation(int extrinsicState)
        {
            Console.WriteLine("具体Flyweight:" + extrinsicState);
        }
    }
}

UnSharedConcreteFlyweight类:编程

namespace FlyweightPattern.BasicStructure
{
    class UnSharedConcreteFlyweight : Flyweight
    {
        public override void Operation(int extrinsicState)
        {
            Console.WriteLine("不共享的具体Flyweight:" + extrinsicState);
        }
    }
}

FlyweightFactory类:ide

namespace FlyweightPattern.BasicStructure
{
    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];
        }
    }
}

客户端调用代码:网站

static void Main(string[] args)
    {
        try
        {
            {//BasicStructure
                int extrinsicState = 22;
                FlyweightFactory flyweightFactory = new FlyweightFactory();
                var flyweight = flyweightFactory.GetFlyweight("X");
                flyweight.Operation(--extrinsicState);

                flyweight = flyweightFactory.GetFlyweight("Y");
                flyweight.Operation(--extrinsicState);

                flyweight = flyweightFactory.GetFlyweight("Z");
                flyweight.Operation(--extrinsicState);

                UnSharedConcreteFlyweight uf = new UnSharedConcreteFlyweight();
                uf.Operation(--extrinsicState);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();
    }

结果以下:this

用外观模式实现网站共享代码

场景模拟:因为多个客户须要作网站,其中有一些客户的网站是基本同样的,只有数据不同。spa

WebSite(网站抽象)类——Flyweight类code

namespace FlyweightPattern.SituationSimulation
{
    /// <summary>
    /// 网站抽象类
    /// </summary>
    abstract class WebSite
    {
        public abstract void Use();
    }
}

ConcreteWebSite(具体网站)类——ConcreteFlyweight类对象

namespace FlyweightPattern.SituationSimulation
{
    /// <summary>
    /// 具体网站类
    /// </summary>
    class ConcreteWebSite : WebSite
    {
        public string Name { get; }
        public ConcreteWebSite(string name)
        {
            this.Name = name;
        }
        public override void Use()
        {
            Console.WriteLine("网站分类:" + Name);
        }
    }
}

WebSiteFactory(网站工厂)类——FlyweightFactory类

namespace FlyweightPattern.SituationSimulation
{
    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;
        }
    }
}

客户端调用代码:

static void Main(string[] args)
    {
        try
        {
            {//SituationSimulation
                WebSiteFactory webSiteFactory = new WebSiteFactory();
                var fx = webSiteFactory.GetWebSiteCategory("产品展现");
                fx.Use();
                var fy = webSiteFactory.GetWebSiteCategory("产品展现");
                fy.Use();
                var fz = webSiteFactory.GetWebSiteCategory("产品展现");
                fz.Use();
                var fl = webSiteFactory.GetWebSiteCategory("博客");
                fl.Use();
                var fm = webSiteFactory.GetWebSiteCategory("博客");
                fm.Use();
                var fn = webSiteFactory.GetWebSiteCategory("博客");
                fn.Use();

                Console.WriteLine($"网站分类总数为:{webSiteFactory.GetWebSiteCount()}");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();
    }

结果以下:

优势:

享元模式的优势

  • 享元模式的优势在于它能够极大减小内存中对象的数量,使得相同对象或类似对象在内存中只保存一份。
  • 享元模式的外部状态相对独立,并且不会影响其内部状态,从而使得享元对象能够在不一样的环境中被共享。

缺点:

享元模式的缺点

  • 享元模式使得系统更加复杂,须要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
  • 为了使对象能够共享,享元模式须要将享元对象的状态外部化,而读取外部状态使得运行时间变长。

适用环境:

在如下状况下可使用享元模式:

  • 一个系统有大量相同或者类似的对象,因为这类对象的大量使用,形成内存的大量耗费。
  • 对象的大部分状态均可之外部化,能够将这些外部状态传入对象中。
  • 使用享元模式须要维护一个存储享元对象的享元池,而这须要耗费资源,所以,应当在屡次重复使用享元对象时才值得使用享元模式。

总结:

  • 享元模式运用共享技术有效地支持大量细粒度对象的复用。系统只使用少许的对象,而这些对象都很类似,状态变化很小,能够实现对象的屡次复用,它是一种对象结构型模式。
  • 享元模式包含四个角色:抽象享元类声明一个接口,经过它能够接受并做用于外部状态;具体享元类实现了抽象享元接口,其实例称为享元对象;非共享具体享元是不能被共享的抽象享元类的子类;享元工厂类用于建立并管理享元对象,它针对抽象享元类编程,将各类类型的具体享元对象存储在一个享元池中。
  • 享元模式以共享的方式高效地支持大量的细粒度对象,享元对象能作到共享的关键是区份内部状态和外部状态。其中内部状态是存储在享元对象内部而且不会随环境改变而改变的状态,所以内部状态能够共享;外部状态是随环境改变而改变的、不能够共享的状态。
  • 享元模式主要优势在于它能够极大减小内存中对象的数量,使得相同对象或类似对象在内存中只保存一份;其缺点是使得系统更加复杂,而且须要将享元对象的状态外部化,而读取外部状态使得运行时间变长。
  • 享元模式适用状况包括:一个系统有大量相同或者类似的对象,因为这类对象的大量使用,形成内存的大量耗费;对象的大部分状态均可之外部化,能够将这些外部状态传入对象中;屡次重复使用享元对象。

 

源代码地址:https://github.com/houzhenhuang/DesignPattern

相关文章
相关标签/搜索