C#设计模式读书笔记之享元模式(Flyweight Pattern)

26 篇文章 16 订阅

享元模式(Flyweight Pattern)【使用频率:★★★☆☆】

1. 概述

  运用共享技术有效地支持大量细粒度的对象。

内部状态:在享元对象内部不随外界环境改变而改变的共享部分。

外部状态:随着环境的改变而改变,不能够共享的状态就是外部状态。

享元模式的核心在于享元工厂类,享元工厂类的作用在于提供一个用于存储享元对象的享元池,用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象。

2. 模式中的角色

  2.1 抽象享元类(Flyweight):通常是一个接口或抽象类,声明具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法设置外部数据(外部状态);

  2.2 具体享元类(ConcreteFlyweight):实现了抽象享元类,通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。

  2.3 非共享具体享元类(UnsharedConcreteFlyweight):并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可以设计为非共享具体享元类。

  2.4 享元工厂类(FlyweightFactory):享元工厂用于创建并管理享元对象,将各种类型的具体享元对象存储在一个享元池中。

3. 模式解读

  3.1 模式的类图

 

       3.2 代码实现

using System;
using System.Collections.Generic;

namespace ConsoleApp2
{
    class Class8
    {
        public static void Main(string[] args)
        {
            //获取享元工厂对象
            IgoChessmanFactory factory = IgoChessmanFactory.Instance;

            //通过享元工厂获取两颗黑子
            IgoChessman black1 = factory.GetIgoChessman("b");
            IgoChessman black2 = factory.GetIgoChessman("b");
            Console.WriteLine("判断两颗黑子是否相同:" + (black1 == black2));

            //通过享元工厂获取两颗白子
            IgoChessman white1 = factory.GetIgoChessman("w");
            IgoChessman white2 = factory.GetIgoChessman("w");
            Console.WriteLine("判断两颗白子是否相同:" + (white1 == white2));

            //显示棋子
            black1.Display();
            black2.Display();
            white1.Display();
            white2.Display();

            Console.ReadLine();
        }
    }

    //围棋棋子类:抽象享元类
    public abstract class IgoChessman
    {
        public abstract string GetColor();

        public void Display()
        {
            Console.WriteLine("棋子颜色:" + GetColor());
        }
    }

    //黑色棋子类:具体享元类
    public class BlackIgoChessman : IgoChessman
    {
        public override string GetColor()
        {
            return "黑色";
        }
    }

    //白色棋子类:具体享元类
    public class WhiteIgoChessman : IgoChessman
    {
        public override string GetColor()
        {
            return "白色";
        }
    }

    //围棋棋子工厂类:享元工厂类,使用单例模式进行设计
    public class IgoChessmanFactory
    {
        private static IgoChessmanFactory m_Instance = new IgoChessmanFactory();
        //使用Dictionary来存储享元对象,充当享元池
        private static Dictionary<string, IgoChessman> m_Dic; 

        private IgoChessmanFactory()
        {
            m_Dic = new Dictionary<string, IgoChessman>();
            IgoChessman black = new BlackIgoChessman();
            m_Dic.Add("b", black);
            IgoChessman white = new WhiteIgoChessman();
            m_Dic.Add("w", white);
        }

        //返回享元工厂类的唯一实例
        public static IgoChessmanFactory Instance
        {
            get
            {
                if (m_Instance == null)
                {
                    m_Instance = new IgoChessmanFactory();
                }
                return m_Instance;
            }
        }

        //通过key来获取存储在Dictionary中的享元对象
        public IgoChessman GetIgoChessman(string color)
        {
            IgoChessman chessman;
            if (m_Dic.TryGetValue(color, out chessman))
            {
                return chessman;
            }
            return chessman;
        }
    }

}

4、 模式优缺点

4.1 优点

  • 能够极大的减少系统中对象的个数,使得相同或相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能。
  • 享元模式由于使用了外部状态,外部状态相对独立,不会影响到内部状态,所以享元模式使得享元对象能够在不同的环境被共享。

4.2 缺点

  • 由于享元模式需要区分外部状态和内部状态,使得应用程序在某种程度上来说更加复杂化了。
  • 为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。

 

5、 模式适用场景

  • 如果一个系统中存在大量的相同或者相似的对象,由于这类对象的大量使用,会造成系统内存的耗费,可以使用享元模式来减少系统中对象的数量。
  • 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
  • 游戏开发中的对象池技术。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值