大话设计模式:享元模式

一、什么是享元模式
使用共享对象可有效地支持大量的细粒度的对象

主要用于减少创建对象,以减少内存占用和提高性能。是对象池的一种实现,避免不停地创建对象销毁对象,把对象状态分为内部状态和外部状态,内部状态是共享不变的,外部状态是可改变的。

UML图

在这里插入图片描述

Flyweight: 是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
ConcreteFlyweight:具体的享元类,更丰富的细节
FlyweightFactory:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

二、适用场景

缓冲池,围棋下子,敌方NPC。系统中存在大量的相似对象细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份,需要缓冲池的场景。比如FPS模式中射出去的子弹,不用的子弹可以回收的,再次发射就是已经实例的子弹。

三、优缺点

优点
大大减少对象创建,节省内存空间和资源

缺点
为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。
读取享元模式的外部状态会使得运行时间稍微变长。

四、大话中的例子

创建网站的例子,有许许多多个人博客和陈列网页,利用享元模式,可以节省内存空间。建立一个网站抽象类,定义公共接口和外部参数。用户类存放用户名信息,具体的网站类实现公共接口,并接受外部信息,也就是用户信息。一个网站工厂类,可获得网站实例,如果不存在实例则实例网站,如果存在了就不必实例了。

五、我的例子
using System;
using System.Collections;
using System.Reflection;

namespace FlyweightMode
{
    class Program
    {
        static void Main(string[] args)
        {

            NinjutsuFactory ninjutsus = new NinjutsuFactory();

            Ninjutsu ninjutsu1 = ninjutsus.CreateNinjutsu("Rasengan");
            ninjutsu1.TakeNinjutsu(new Ninjar("鸣人"), 100);
            Ninjutsu ninjutsu2 = ninjutsus.CreateNinjutsu("Rasengan");
            ninjutsu2.TakeNinjutsu(new Ninjar("自来也"), 160);
            Ninjutsu ninjutsu3 = ninjutsus.CreateNinjutsu("Rasengan");
            ninjutsu3.TakeNinjutsu(new Ninjar("水门"), 220);
            Ninjutsu ninjutsu4 = ninjutsus.CreateNinjutsu("Kagebunsin");
            ninjutsu4.TakeNinjutsu(new Ninjar("卡卡西"), 2);
            Ninjutsu ninjutsu5 = ninjutsus.CreateNinjutsu("Kagebunsin");
            ninjutsu5.TakeNinjutsu(new Ninjar("鸣人"), 1000);

            Console.WriteLine("数量:" + ninjutsus.GetNinjusuNum());
            Console.ReadKey();
        }
    }


    /// <summary>
    /// 忍术
    /// </summary>
    abstract class Ninjutsu
    {
        protected string name;


        /// <summary>
        /// 施展技能
        /// </summary>
        /// <param name="ninjar">谁施展技能</param>
        /// <param name="para">技能参数</param>
        public abstract void TakeNinjutsu(Ninjar ninjar, int para);

    }

    /// <summary>
    /// 螺旋丸
    /// </summary>
    class Rasengan : Ninjutsu
    {
        public Rasengan()
        {
            name = "螺旋丸";
        }

        public override void TakeNinjutsu(Ninjar ninjar, int para)
        {
            Console.WriteLine("{0}使用了{1}", ninjar.Name, name);
            Console.WriteLine("造成{0}点伤害.", para);
        }
    }

    /// <summary>
    /// 隐分身
    /// </summary>
    class Kagebunsin : Ninjutsu
    {
        public Kagebunsin()
        {
            name = "隐分身术";
        }
        public override void TakeNinjutsu(Ninjar ninjar, int para)
        {
            Console.WriteLine("{0}使用了{1}", ninjar.Name, name);
            Console.WriteLine("增加{0}个分身", para);
        }
    }

    /// <summary>
    /// 忍者,存个名字
    /// </summary>
    public class Ninjar
    {
        string name;
        public Ninjar(string name)
        {
            this.name = name;
        }

        public string Name { get => name; }
    }


    /// <summary>
    /// 忍术工厂
    /// </summary>
    class NinjutsuFactory
    {
        Hashtable ninjutsus = new Hashtable();//哈希表,存已经实例的忍术的


        /// <summary>
        /// 生成忍术
        /// </summary>
        /// <param name="key">忍术关键词</param>
        /// <returns></returns>
        public Ninjutsu CreateNinjutsu(string key)
        {

            if (!ninjutsus.ContainsKey(key))
            {
                var asmb = Assembly.GetExecutingAssembly();//使用反射,获得当前程序集
                var t = asmb.CreateInstance("FlyweightMode." + key);//程序集通过类的完全限定名实例
                ninjutsus.Add(key, t);//存储起来
            }

            return (Ninjutsu)ninjutsus[key];
        }

        /// <summary>
        /// 获得实例个数
        /// </summary>
        /// <returns></returns>
        public int GetNinjusuNum()
        {
            return ninjutsus.Count;
        }
    }
}

运行结果

在这里插入图片描述
PS:享元模式,其实是缓冲池的运用, 关键在于将细粒度不同的对象共享为同一对象,节省内存资源。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值