享元模式

1.简介

  享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

  我们这里新建H、E、L、O四个类,每个类返回对应的字母,用来打印HELLO。

  首先,新建一个抽象类,用来规定H、E、L、O四个类需要有相同的操作DisPlay

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FlyweightPattern
{
    public abstract class BaseWord
    {
        public abstract string DisPlay();
    }
}

  H类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FlyweightPattern
{
    class H:BaseWord
    {
        public H()
        {
            Thread.Sleep(500);
            Console.WriteLine("字母H被构造");
        }
        public override string DisPlay()
        {
            return "H";
        }
    }
}

  E类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace FlyweightPattern
{
    class E : BaseWord
    {
        public E()
        {
            Thread.Sleep(500);
            Console.WriteLine("字母E被构造");
        }
        public override string DisPlay()
        {
            return "E";
        }
    }
}

  L类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace FlyweightPattern
{
    class L:BaseWord
    {
        public L()
        {
            Thread.Sleep(500);
            Console.WriteLine("字母L被构造");
        }
        public override string DisPlay()
        {
            return "L";
        }
    }
}

  O类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FlyweightPattern
{
    class O:BaseWord
    {
        public O()
        {
            Thread.Sleep(500);
            Console.WriteLine("字母O被构造");
        }
        public override string DisPlay()
        {
            return "O";
        }
    }
}

  接下来是享元模式的核心

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FlyweightPattern
{
    public class FlyWeightFactory//享元工厂
    {
        private static Dictionary<WordType, BaseWord> _BaseWorldDictionary = new Dictionary<WordType, BaseWord>();//用字典保存关键字和类的实例
        public static BaseWord GetWord(WordType wordType)
        {
            BaseWord baseWord = null;
            if (_BaseWorldDictionary.ContainsKey(wordType))//如果字典中已经有这个实例,就直接使用,没有就新增
            {
                baseWord = _BaseWorldDictionary[wordType];
            }
            else
            {
                switch (wordType)
                {
                    case WordType.E: baseWord = new E(); break;
                    case WordType.H: baseWord = new H(); break;
                    case WordType.L: baseWord = new L(); break;
                    case WordType.O: baseWord = new O(); break;
                    default:throw new Exception("wrong wordType");
                }
                _BaseWorldDictionary.Add(wordType, baseWord);
            }
            return baseWord;
        }
    }
    public enum WordType
    {
        H,E,L,O
    }
}

  Program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FlyweightPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            show1();
            show2();
            Console.Read();
        }
        static void show1()
        {
            Console.WriteLine("--------------------show1-----------------------");
            BaseWord baseWord1 = FlyWeightFactory.GetWord(WordType.H);
            BaseWord baseWord2 = FlyWeightFactory.GetWord(WordType.E);
            BaseWord baseWord3 = FlyWeightFactory.GetWord(WordType.L);
            BaseWord baseWord4 = FlyWeightFactory.GetWord(WordType.L);
            BaseWord baseWord5 = FlyWeightFactory.GetWord(WordType.O);
            Console.Write(baseWord1.DisPlay());
            Console.Write(baseWord2.DisPlay());
            Console.Write(baseWord3.DisPlay());
            Console.Write(baseWord4.DisPlay());
            Console.Write(baseWord5.DisPlay());
            Console.WriteLine();
        }

        static void show2()
        {
            Console.WriteLine("--------------------show2-----------------------");
            BaseWord baseWord1 = FlyWeightFactory.GetWord(WordType.H);
            BaseWord baseWord2 = FlyWeightFactory.GetWord(WordType.E);
            BaseWord baseWord3 = FlyWeightFactory.GetWord(WordType.L);
            BaseWord baseWord4 = FlyWeightFactory.GetWord(WordType.L);
            BaseWord baseWord5 = FlyWeightFactory.GetWord(WordType.O);
            Console.Write(baseWord1.DisPlay());
            Console.Write(baseWord2.DisPlay());
            Console.Write(baseWord3.DisPlay());
            Console.Write(baseWord4.DisPlay());
            Console.Write(baseWord5.DisPlay());
            Console.WriteLine();
        }
    }
}

 2.多线程享元模式

  当我们使用多线程的时候,上面的例子并不稳定

  很大可能会发生错误

  对Program的Main函数进行修改,启用多线程

static void Main(string[] args)
        {
            new Action(show1).BeginInvoke(null, null);
            new Action(show2).BeginInvoke(null, null);

            Console.Read();
        }

  执行的时候两个线程会同步进行

  结果如下:

     H类被实例化了两次,字典添加相同的键,发生错误

  可以对享元工厂进行双if+lock锁来解决这个问题

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FlyweightPattern
{
    public class FlyWeightFactory//享元工厂
    {
        static object FlyWeight_Lock = new object();//定义一个静态object参数,用来做lock的参数
        private static Dictionary<WordType, BaseWord> _BaseWorldDictionary = new Dictionary<WordType, BaseWord>();//用字典保存关键字和类的实例
        public static BaseWord GetWord(WordType wordType)
        {
            BaseWord baseWord = null;
            if (_BaseWorldDictionary.ContainsKey(wordType))
            {
                baseWord = _BaseWorldDictionary[wordType];
            }
            else
            {
                lock (FlyWeight_Lock)
                {
                    if (_BaseWorldDictionary.ContainsKey(wordType))//如果字典中已经有这个实力,就直接使用,没有就新增
                    {
                        baseWord = _BaseWorldDictionary[wordType];
                    }
                    else
                    {
                        switch (wordType)
                        {
                            case WordType.E: baseWord = new E(); break;
                            case WordType.H: baseWord = new H(); break;
                            case WordType.L: baseWord = new L(); break;
                            case WordType.O: baseWord = new O(); break;
                            default: throw new Exception("wrong wordType");
                        }
                        _BaseWorldDictionary.Add(wordType, baseWord);
                    }
                }
            }
            return baseWord;
        }
    }
    public enum WordType
    {
        H,E,L,O
    }
}

   执行结果:

  因为多线程的无序性,打印结果并不是我们期待的结果

  可以对打印代码进行一下修改

  

  修改为:

  

  结果:

 

posted @ 2018-06-29 12:51  wskxy  阅读(171)  评论(0编辑  收藏  举报