c#设计模式系类:亨元模式

2021-07-14 12:14

阅读:353

标签:代码   利用   状态   new   子类   问题   资源   add   code   

一、引言

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

二、享元模式的详细介绍

  既然亨元模式可以解决重复使用new创建对象的问题,下面让我们分析下如何去解决上面那个问题,既然都是同一个对象,能不能只创建一个对象,然后下次需要创建这个对象的时候,让它直接用已经创建好了的对象就好了呢,也就是说让一个对象共享。这个也是亨元模式的实现精髓所在。

2.1 定义

介绍完享元模式的精髓之后,让我们具体看看享元模式的正式定义:

亨元模式——利用共享技术有效地支持大量细粒度的类实例来表示数据,亨元模式可以避免大量相识类的开销,在软件开发过程中如果需要大量细粒度的类实例来表示数据,而这些实例除了几个参数外基本相同,这时候就可以使用亨元模式来大幅度减少需要类的实例数量。如果能把这些参数(指的这些类实例的不同参数)移动到类实例外面,在方法调用时将他们传入尽量,这样就可以通过共享大幅度减少单个实例的数目,然而我们把类实例外面的参数称为亨元对象的外部状态,把亨元对象内部参数称为内部状态,

  • 内部状态:在亨元对象的内部,并且不会随着环境的改变而改变的共享部分
  • 外部对象:随环境的变化而改变的,部可以共享的部分。

2.2 亨元模式结构图

技术分享图片

2.3 亨元模式的组成

  • 抽象亨元角色(Flyweight):此角色是所有的具体亨元类的基类,为这些类规定出需要实现的公共接口,那些需要外部状态的操作可以通过调用方法已参数形式传递。
  • 具体亨元角色(ConcreteFlyweight):实现抽象亨元角色所规定的接口,如果又内部状态的化,可以在类内部定义。
  • 亨元工厂角色(FlyweightFactory):本角色负责创建和管理亨元角色,本角色保证亨元对象可以被共享,当一个客户端调用一个亨元对象的时候,亨元工厂角色检查系统是否已经有一个符合的亨元对象,如果已经存在,就返回亨元对象,如果不存在就重新创建一个亨元对象
  • 客户端角色(Client):本角色需要存储亨元对象的外部状态

2.4亨元模式代码实现

  Flyweight类,它是所有具体亨元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态

技术分享图片技术分享图片
public abstract class Flywieght
    {
        public abstract void Operation(int extrinsicstate);
    }
View Code

ConcreteFlyweight是继承Flyweight超类或实现Flyweight接口,并为内部状态增加存储空间。

技术分享图片技术分享图片
   public class ConcreteFlyweight:Flywieght
    {
        public override void Operation(int extrinsicstate)
        {
            Console.WriteLine("具体的"+extrinsicstate);
        }
    }
View Code

UnsharedConcreteFlyweight是 指那些不需要共享的Flyweight子类,因为Flyweight接口让共享成为可能,但它并不强制共享

技术分享图片技术分享图片
    public class UnsharedConcreteFlyweight:Flywieght
    {
        public override void Operation(int extrinsicstate)
        {
            Console.WriteLine("不共享的具体Flywieght"+extrinsicstate);
        }
    }
View Code
FlyweightFactory,是一个亨元工厂,用来创建并管理Flyweight对象,它主要是用来确保合理的共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在)
技术分享图片技术分享图片
   public  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 Flywieght GetFlyweight(string key)
        {
            return ((Flywieght)flyweights[key]) ;
        }
    }
View Code

客户端代码

技术分享图片技术分享图片
    class Program
    {
        static void Main(string[] args)
        {
            int extrinsincstate = 10;
            FlyweightFactory f = new FlyweightFactory();

            Flywieght fx = f.GetFlyweight("X");
            fx.Operation(--extrinsincstate);

            Flywieght fy = f.GetFlyweight("Y");
            fy.Operation(--extrinsincstate);

            Flywieght fz = f.GetFlyweight("Z");
            fz.Operation(--extrinsincstate);

            UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight();
            uf.Operation(--extrinsincstate);

            Console.Read();
        }
    }
View Code

结果表示

技术分享图片技术分享图片
具体的9
具体的8
具体的7
不共享的具体Flywieght6
View Code

三、享元模式的实现要点:

    面向对象很好地解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight设计模式主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。
    Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理。
 对象的数量太大从而导致对象内存开销加大——什么样的数量才算大?这需要我们仔细的根据具体应用情况进行评估,而不能凭空臆断。

  • 享元模式的优点
  1. 享元模式的优点在于它能够极大的减少系统中对象的个数。
  2. 元模式由于使用了外部状态,外部状态相对独立,不会影响到内部状态,所以享元模式使得享元对象能够在不同的环境被共享。
  • 享元模式的缺点
  1. 于享元模式需要区分外部状态和内部状态,使得应用程序在某种程度上来说更加复杂化了。
  2. 为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变
  • 在下面所有条件都满足时,可以考虑使用享元模式:
  1. 一个系统中有大量的对象;
  2. 这些对象耗费大量的内存;
  3. 这些对象中的状态大部分都可以被外部化
  4. 这些对象可以按照内部状态分成很多的组,当把外部对象从对象中剔除时,每一个组都可以仅用一个对象代替软件系统不依赖这些对象的身份,

满足上面的条件的系统可以使用享元模式。但是使用享元模式需要额外维护一个记录子系统已有的所有享元的表,而这也需要耗费资源,所以,应当在有足够多的享元实例可共享时才值得使用享元模式。

  通过迭代来使用模式,别为了模式而模式

c#设计模式系类:亨元模式

标签:代码   利用   状态   new   子类   问题   资源   add   code   

原文地址:https://www.cnblogs.com/studydp/p/9539652.html


评论


亲,登录后才可以留言!