深入理解设计模式(22):享元模式

一、引言

大家都知道单例模式,通过一个全局变量来避免重复创建对象而产生的消耗,若系统存在大量的相似对象时,又该如何处理?参照单例模式,可通过对象池缓存可共享的对象,避免创建多对象,尽可能减少内存的使用,提升性能,防止内存溢出。

在软件开发过程,如果我们需要重复使用某个对象的时候,如果我们重复地使用new创建这个对象的话,这样我们在内存就需要多次地去申请内存空间了,这样可能会出现内存使用越来越多的情况,这样的问题是非常严重,然而享元模式可以解决这个问题,下面具体看看享元模式是如何去解决这个问题的。

二、什么是享元模式

定义:共享元对象,运用共享技术有效地支持大量细粒度对象的复用。如果在一个系统中存在多个相同的对象,那么只需要共享一份对象的拷贝,而不必为每一次使用创建新的对象。

享元模式是为数不多的、只为提升系统性能而生的设计模式,主要作用就是复用大对象(重量级对象),以节省内存空间和对象创建时间。

  面向对象可以非常方便的解决一些扩展性的问题,但是在这个过程中系统务必会产生一些类或者对象,如果系统中存在对象的个数过多时,将会导致系统的性能下降。对于这样的问题解决最简单直接的办法就是减少系统中对象的个数。享元模式提供了一种解决方案,使用共享技术实现相同或者相似对象的重用。也就是说实现相同或者相似对象的代码共享。

所谓享元模式就是运行共享技术有效地支持大量细粒度对象的复用。系统使用少量对象,而且这些都比较相似,状态变化小,可以实现对象的多次复用。

共享模式是支持大量细粒度对象的复用,所以享元模式要求能够共享的对象必须是细粒度对象。

首先了解两个概念:内部状态、外部状态。

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

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

由于享元模式区分了内部状态和外部状态,所以我们可以通过设置不同的外部状态使得相同的对象可以具备一些不同的特性,而内部状态设置为相同部分。

在我们的程序设计过程中,我们可能会需要大量的细粒度对象来表示对象,如果这些对象除了几个参数不同外其他部分都相同,这个时候我们就可以利用享元模式来大大减少应用程序当中的对象。

如何利用享元模式呢?这里我们只需要将他们少部分的不同的部分当做参数移动到类实例的外部,然后在方法调用的时候将他们传递过来就可以了。这里也就说明了一点:内部状态存储于享元对象内部,而外部状态则应该由客户端来考虑。

三、享元模式的结构

  1. Flyweight: 享元接口,所有具体享元类的超类或接口,通过该接口Flyweight可以接受并作用于外部状态。通过该接口可以传入外部的状态,在享元对象的方法处理中可能会使用这些外部的数据。
  2. ConcreteFlyweight: 具体的享元实现对象,指定内部状态,必须是共享的,需要封装Flyweight的内部状态。
  3. UnshareConcreteFlyweight: 非共享的享元实现对象,并不是所有的Flyweight实现对象都需要共享。非共享的享元实现对象通常是对享元对象的组合对象。
  4. FlyweightFactoty: 享元工厂类,主要用来创建并管理共享的享元对象,并对外提供访问共享享元的接口。当用户请求一个Flyweight时,FlyweightFactory就会提供一个已经创建的Flyweight对象或者新建一个(如果不存在)。
  5. Client: 享元客户端,主要的工作就是维持一个对Flyweight的引用,计算或存储享元的外部状态,当然这里可访问共享和不共享的Flyweight对象。

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

四、享元模式和单例模式的异同

享元模式可以再次创建对象 也可以取缓存对象

单例模式则是严格控制单个进程中只有一个实例对象

享元模式可以通过自己实现对外部的单例 也可以在需要的使用创建更多的对象

单例模式是自身控制 需要增加不属于该对象本身的逻辑

两者都可以实现节省对象创建的时间 ThreadPool 线程池 与数据库连接池 都有使用享元模式

五、享元模式的优缺点

优点

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

缺点

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

六、享元模式的使用场景

  • 一个系统有大量相同或者相似的对象,造成内存的大量耗费。
  • 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
  • 在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式。

七、享元模式的实现

public abstract class abStudent
    {
        public string Name;
        public string schName;
        public string Sex;
        public abStudent()
        {
            schName = "吉林大学";
            Sex = "男";
        }

        public override string ToString()
        {
            return string.Format("我叫{0},性别{1},在读学校{2}", Name, Sex, schName);
        }
    }
public class Student:abStudent
    {
        public Student(string name)
        {
            Name = name;
        }
    }
public class School
    {
        private Dictionary<int, Student> StudentList;
        public School()
        {
            StudentList = new Dictionary<int, Student>();
            StudentList.Add(1, new Student("张三"));
            StudentList.Add(2, new Student("李四"));
        }
        public Student GetStudent(int num)
        {
            return StudentList[num] as Student;
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            School school = new School();
            Student student = school.GetStudent(1);
            Console.WriteLine(student.ToString());
            student = school.GetStudent(2);
            Console.WriteLine(student.ToString());
            Console.ReadKey();
        }
    }

八、总结

  1、享元模式可以极大地减少系统中对象的数量。但是它可能会引起系统的逻辑更加复杂化。

2、享元模式的核心在于享元工厂,它主要用来确保合理地共享享元对象。

3、内部状态为不变共享部分,存储于享元享元对象内部,而外部状态是可变部分,它应当油客户端来负责。

原文地址:https://www.cnblogs.com/xuwendong/p/10414863.html

时间: 2024-10-03 13:46:01

深入理解设计模式(22):享元模式的相关文章

设计模式之享元模式

Flyweight在拳击比赛中指最轻量级,即"蝇量级"或"雨量级",这里选择使用"享元模式"的意译,是因为这样更能反映模式的用意.享元模式是对象的结构模式.享元模式以共享的方式高效地支持大量的细粒度对象. Java中的String类型 在JAVA语言中,String类型就是使用了享元模式.String对象是final类型,对象一旦创建就不可改变.在JAVA中字符串常量都是存在常量池中的,JAVA会确保一个字符串常量在常量池中只有一个拷贝.Stri

纵横之设计模式(享元模式-性能与对象访问)

声明:本系列文章内容摘自<iOS设计模式> 享元模式:运用共享技术有效地支持大量细粒度的对象. 何为享元模式 实现享元模式需要两个关键组件,通常是可共享的享元对象和保存它们的池.某种中央对象维护这个池,并从它返回适当的实例,工厂是这一角色的理想候选.它可以通过一个工厂方法,根据父类型返回各种类型的具体享元对象.其主要目的就是维护池中的享元对象,并适当的从中返回享元对象. 何时使用享元模式 1.应用程序使用很多对象: 2.在内存中保存对象会影响内存性能: 3.对象的多处持有状态(外在状态)可以放

Java设计模式之享元模式实例详解

本文实例讲述了Java设计模式之享元模式.分享给大家供大家参考,具体如下: 解释一下概念:也就是说在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象.比如说一个文本系统,每个字母定一个对象,那么大小写字母一共就是52个,那么就要定义52个对象.如果有一个1M的文本,那么字母是何其的多,如果每个字母都定义一个对象那么内存早就爆了.那么如果要是每个字母都共享一个对象,那么就大大节约了资源. 在Flyweight模式中,由于要产生各种各样的对象,所以在Flyweigh

深入理解JavaScript系列(37):设计模式之享元模式

介绍 享元模式(Flyweight),运行共享技术有效地支持大量细粒度的对象,避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类). 享元模式可以避免大量非常相似类的开销,在程序设计中,有时需要生产大量细粒度的类实例来表示数据,如果能发现这些实例除了几个参数以外,开销基本相同的 话,就可以大幅度较少需要实例化的类的数量.如果能把那些参数移动到类实例的外面,在方法调用的时候将他们传递进来,就可以通过共享大幅度第减少单个实例 的数目. 那么如果在JavaScript中应用享元模式

GOF23设计模式之享元模式之理解

 享元模式(FlyWeight)      内存属于稀缺资源,不要随便浪费.如果有很多个完全相同或相似的对象,我们可以通过享元模式,节省内存.      节省了内存,有些时候,会造成运行时间的加长. 核心:      享元模式以共享的方式高效地支持大量细粒度对象的重用      享元对象能做到共享的关键是区分了内部状态和外部状态.          内部状态:可以共享,不会随环境变化而改变.          外部状态:不可以共享,会随环境变化而改变.   围棋软甲设计:      每个围棋

设计模式之享元模式(Flyweight)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化托付给还有一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些详细的类的信息封装起来.第二,它们隐藏了这些类的实例是怎样被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,

大话设计模式_享元模式(Java代码)

享元模式:运用共享技术有效的支持大量细粒度的对象. 简单描述:1个享元工厂,提供各种类型的享元.如果这些享元存在于工厂对象中,则直接提出给客户端,如果没有,则新建享元并存储起来,同时提供给客户端.享元的外部状态可以由客户端存储并在调用相关需要外部状态的操作时由客户端传入 大话设计模式中的截图: 代码例子: User类: 1 package com.longsheng.flyweight; 2 3 //外部状态 4 public class User { 5 6 private String na

【设计模式】享元模式(Flyweight)

摘要: 1.本文将详细介绍享元模式的原理和实际代码中特别是Android系统代码中的应用. 纲要: 1. 引入享元模式 2. 享元模式的概念及优缺点介绍 3. 享元模式在Android源码中的应用 1.先来一个段子: GG每天给MM至少发一条短信,而且每天入睡前是必有一条短信的,往往是一些琐事和一些比较肉麻的情话.开始的一个月,GG还对此是乐不可支,随着时间的推移,那些肉麻的话说了很多遍,自己也觉得厌烦了,而且更让人不可忍耐的是这些肉麻的情话每次都要重复的输入.GG把这一烦心事告诉了自己的好友K

Java进阶篇设计模式之七 ----- 享元模式和代理模式

前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式. 用通俗的话来说就是进行共用.生活中也有一些例子,比如之前很火的共享单车,更早之前的图书馆,编程中经常用的String类,数据库连接池等等.当然,享元模式主要的目的是复用,如果该对象没有的话,就会进行创建. 享

Head First设计模式之享元模式(蝇量模式)

一.定义 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式. 享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象.我们将通过创建 5 个对象来画出 20 个分布于不同位置的圆来演示这种模式.由于只有 5 种可用的颜色,所以 color 属性被用来检查现有的 Circle 对象. 二.结构 三.实现 namespace DesignPattern