zoukankan      html  css  js  c++  java
  • 面向对象设计模式_享元模式(Flyweight Pattern)解读

    场景:程序需要不断创建大量相似的细粒度对象,会造成严重的内存负载。我们可以选择享元模式解决该问题。

    享元抽象:Flyweight 描述享元的抽象结构。它包含内蕴和外蕴部分(别被术语迷惑,这是一种比较深的描述,浅的来说,内蕴就是对象中不变的数据,外蕴反之,在编程时区分两者的区别就可以了,无需刻意在代码中表达这种术语的含义。)

    享元:ConcreteFlyweight 可用用来共享的对象实例,我们将享元的按照共享性质分为内蕴(不因环境变化而变的部分),外蕴两部分。内蕴是享元的固有特性,不会变化。外蕴需要享元被调用时由外部设置。

    享元池(或叫享元工厂):FlyweightFactory存放享元的地方。

    非共享享元:UnsharedFlyweight 与享元都继承自享元抽象,但其不能被共享。其应用在需要将一个享元组合一起使用,并统一设置外蕴的情景。比如为了提高执行速度,将经常重复出现的对象组(其中每个对象也可以是从享元池中共享抽取出来的)封装到一起,从而执行重复的工作。比如说制图中,由几个基本形状组成的复合形状需要经常被提取出来执行绘制操作。

    模型图如下:

    示例:

    //在一个任务中客户需要绘制大量的正方形
     //其中这些正方形在填充颜色和尺寸上仅有有限的几个固定值。
     //边长是5,10,15,颜色,红,绿,蓝,这代表客户端需求按边长,颜色分组最多有3*3=9组类似的正方形对象。

    //如果每次需要一个正方形对象,其中每个对象关于填充颜色的数据很大,如果都要一一实例化,将会是内存读写,负载不断增大。

     //如果采用享元模式,在享元池中最多存放9种不同内蕴的实例。那么将大大减少内存负载。

    //经常会出现一些同样的组合形状被重复绘制
     //为了提高运行效率,可以将这些重复出现的对象封装到一起执行任务

     //定义享元抽象Flyweight
        public abstract class Rectangle
        {
            //对象的坐标(属于对象的外蕴部分)
            public float PointX { get; set; }
            public float PointY { get; set; }
    
            //内蕴
            public string Color { get; set; }
            //边长
            public float Width { get; set; }
            //设置外蕴
            public abstract void SetStart(float x,float y);
        } 
    
     //定义具体享元
        public class RedRectangle:Rectangle
        {
            public RedRectangle()
            {
                this.Color = "Red";
            }
    
            public override void SetStart(float x,float y)
            {
                this.PointX = x;
                this.PointY = y;
            }
        }
        public class GreenRectangle : Rectangle
        {
            public GreenRectangle()
            {
                this.Color = "Green";
            }
    
            public override void SetStart(float x,float y)
            {
                this.PointX = x;this.PointY = y;
            }
        }
        public class BlueRectangle : Rectangle
        {
            public BlueRectangle()
            {
                this.Color = "Blue";
            }
    
            public override void SetStart(float x,float y)
            {
                this.PointX = x;
                this.PointY = y;
            }
        }
    
     //定义一个非共享元
        public class UshareRectangle : Rectangle
        {
            public List<Rectangle> Rectangles { get; set; }
            public UshareRectangle()
            {
    
            }
    
            public override void SetStart(float x, float y)
            {
                for(int i=0;i<Rectangles.Count;i++)
                {
                    Rectangles[0].PointX = x+i*15;
                    Rectangles[0].PointX = y + i * 15;
                }
               
            }
        }
    
     //定义享元池
        public class FlyweightPool
        {
            public Hashtable Pool { get; set; }
    
    
        }
    
    //定义一个客户端
        public static class Client
        {
            public static void DrawRectangle(Rectangle rectangle,float x,float y)
            {
                rectangle.SetStart(x, y);
                Console.WriteLine("您在({0},{1})处画了一个边长为{2}的{3}正方形"
                    ,rectangle.PointX,rectangle.PointY,rectangle.Width,rectangle.Color);
            }
        }
    
    
    
    //测试代码
    
    public class Test
        {
           private  FlyweightPool pool = new FlyweightPool() { Pool = new Hashtable() };//定义一个工厂实例
    //在平台上画上2000个随机指定类型的正方形
    public void Test1() { //画图开始 //在指定的2000个位置画总共2000个正方形 float[][] position = new float[2000][]; for (int i = 0; i < 2000; i++) { position[i] = new float[2]; position[i][0] = i * 15; position[i][1] = i * 15; } Random random = new Random(1); for (int i = 0; i < 2000; i++) { switch (random.Next(8)) { case 0: if (pool.Pool["r5"]==null) { pool.Pool.Add("r5", new RedRectangle() { Color = "Red", Width = 5 }); } Client.DrawRectangle((Rectangle)pool.Pool["r5"],position[i][0],position[i][1]); break; case 1: if (pool.Pool["r10"] == null) { pool.Pool.Add("r10", new RedRectangle() { Color = "Red", Width = 10 }); } Client.DrawRectangle((Rectangle)pool.Pool["r10"], position[i][0], position[i][1]); break; case 2: if (pool.Pool["r15"] == null) { pool.Pool.Add("r15", new RedRectangle() { Color = "Red", Width = 15 }); } Client.DrawRectangle((Rectangle)pool.Pool["r15"], position[i][0], position[i][1]); break; case 3: if (pool.Pool["g5"] == null) { pool.Pool.Add("g5", new GreenRectangle() { Color = "Green", Width = 5 }); } Client.DrawRectangle((Rectangle)pool.Pool["g5"], position[i][0], position[i][1]); break; case 4: if (pool.Pool["g10"] == null) { pool.Pool.Add("g10", new GreenRectangle() { Color = "Green", Width = 10 }); } Client.DrawRectangle((Rectangle)pool.Pool["g10"], position[i][0], position[i][1]); break; case 5: if (pool.Pool["g15"] == null) { pool.Pool.Add("g15", new GreenRectangle() { Color = "Green", Width = 15 }); } Client.DrawRectangle((Rectangle)pool.Pool["g15"], position[i][0], position[i][1]); break; case 6: if (pool.Pool["b5"] == null) { pool.Pool.Add("b5", new BlueRectangle() { Color = "Blue", Width = 5 }); } Client.DrawRectangle((Rectangle)pool.Pool["b5"], position[i][0], position[i][1]); break; case 7: if (pool.Pool["b10"] == null) { pool.Pool.Add("b10", new BlueRectangle() { Color = "Blue", Width = 10 }); } Client.DrawRectangle((Rectangle)pool.Pool["b10"], position[i][0], position[i][1]); break; case 8: if (pool.Pool["b15"] == null) { pool.Pool.Add("b15", new BlueRectangle() { Color = "Blue", Width = 15 }); } Client.DrawRectangle((Rectangle)pool.Pool["b15"], position[i][0], position[i][1]); break; default: break; } } } //重复绘制图形组合 public void Test2() { //重复绘制某组合 UshareRectangle urs = new UshareRectangle(); if (pool.Pool["r5"] == null) { pool.Pool.Add("r5", new RedRectangle() { Color = "Red", Width = 5 }); } urs.Rectangles.Add((Rectangle)pool.Pool["r5"]); if (pool.Pool["r10"] == null) { pool.Pool.Add("r10", new RedRectangle() { Color = "Red", Width = 5 }); } urs.Rectangles.Add((Rectangle)pool.Pool["r10"]); int x = 0, y = 0; for (int i = 0; i < 20; i++) { foreach (Rectangle r in urs.Rectangles) { Client.DrawRectangle(r, x,y); x += 15;y += 15; } } } }
  • 相关阅读:
    Danny_Su的devexpress 9.3.3的注册插件在vs2010RC中无法使用的解决办法
    EntitySpaces2009中的关系
    EntitySpaces2009的开发文档地址
    EntitySpaces2009支持事务
    EntitySpaces2009中连接Access的连接设置
    基于matlab的视频测速处理
    图像拼接与融合
    某图像分析系统
    黑子数与开盘指数相关性分析
    另类的图像处理
  • 原文地址:https://www.cnblogs.com/JoeBlogs/p/8602895.html
Copyright © 2011-2022 走看看