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

享元抽象: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=;i<Rectangles.Count;i++)
{
Rectangles[].PointX = x+i*;
Rectangles[].PointX = y + i * ;
} }
} //定义享元池
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[][]; for (int i = ; i < ; i++)
{
position[i] = new float[];
position[i][] = i * ;
position[i][] = i * ;
} Random random = new Random();
for (int i = ; i < ; i++)
{
switch (random.Next())
{
case :
if (pool.Pool["r5"]==null)
{
pool.Pool.Add("r5", new RedRectangle() { Color = "Red", Width = }); } Client.DrawRectangle((Rectangle)pool.Pool["r5"],position[i][],position[i][]);
break;
case :
if (pool.Pool["r10"] == null)
{
pool.Pool.Add("r10", new RedRectangle() { Color = "Red", Width = });
}
Client.DrawRectangle((Rectangle)pool.Pool["r10"], position[i][], position[i][]);
break;
case :
if (pool.Pool["r15"] == null)
{
pool.Pool.Add("r15", new RedRectangle() { Color = "Red", Width = });
}
Client.DrawRectangle((Rectangle)pool.Pool["r15"], position[i][], position[i][]);
break;
case :
if (pool.Pool["g5"] == null)
{
pool.Pool.Add("g5", new GreenRectangle() { Color = "Green", Width = });
}
Client.DrawRectangle((Rectangle)pool.Pool["g5"], position[i][], position[i][]);
break;
case :
if (pool.Pool["g10"] == null)
{
pool.Pool.Add("g10", new GreenRectangle() { Color = "Green", Width = });
}
Client.DrawRectangle((Rectangle)pool.Pool["g10"], position[i][], position[i][]);
break;
case :
if (pool.Pool["g15"] == null)
{
pool.Pool.Add("g15", new GreenRectangle() { Color = "Green", Width = });
}
Client.DrawRectangle((Rectangle)pool.Pool["g15"], position[i][], position[i][]);
break;
case :
if (pool.Pool["b5"] == null)
{
pool.Pool.Add("b5", new BlueRectangle() { Color = "Blue", Width = });
}
Client.DrawRectangle((Rectangle)pool.Pool["b5"], position[i][], position[i][]);
break;
case :
if (pool.Pool["b10"] == null)
{
pool.Pool.Add("b10", new BlueRectangle() { Color = "Blue", Width = });
}
Client.DrawRectangle((Rectangle)pool.Pool["b10"], position[i][], position[i][]);
break;
case :
if (pool.Pool["b15"] == null)
{
pool.Pool.Add("b15", new BlueRectangle() { Color = "Blue", Width = });
}
Client.DrawRectangle((Rectangle)pool.Pool["b15"], position[i][], position[i][]);
break;
default:
break;
}
} } //重复绘制图形组合
public void Test2()
{
//重复绘制某组合
UshareRectangle urs = new UshareRectangle();
if (pool.Pool["r5"] == null)
{
pool.Pool.Add("r5", new RedRectangle() { Color = "Red", Width = }); }
urs.Rectangles.Add((Rectangle)pool.Pool["r5"]);
if (pool.Pool["r10"] == null)
{
pool.Pool.Add("r10", new RedRectangle() { Color = "Red", Width = }); }
urs.Rectangles.Add((Rectangle)pool.Pool["r10"]);
int x = , y = ;
for (int i = ; i < ; i++)
{ foreach (Rectangle r in urs.Rectangles)
{ Client.DrawRectangle(r, x,y);
x += ;y += ; } }
}
}

面向对象设计模式_享元模式(Flyweight Pattern)解读的更多相关文章

  1. 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern)

    原文:乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) 作者:weba ...

  2. 设计模式-11享元模式(Flyweight Pattern)

    1.模式动机 在面向对象程序设计过程中,有时会面临要创建大量相同或相似对象实例的问题.创建那么多的对象将会耗费很多的系统资源,它是系统性能提高的一个瓶颈. 享元模式就是把相同或相似对象的公共部分提取出 ...

  3. 二十四种设计模式:享元模式(Flyweight Pattern)

    享元模式(Flyweight Pattern) 介绍运用共享技术有效地支持大量细粒度的对象. 示例有一个Message实体类,某些对象对它的操作有Insert()和Get()方法,现在要运用共享技术支 ...

  4. 【UE4 设计模式】享元模式 Flyweight Pattern

    概述 描述 运用共享技术有效地支持大量细粒度对象的复用.系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用. 由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻 ...

  5. 设计模式系列之享元模式(Flyweight Pattern)——实现对象的复用

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  6. Java享元模式(Flyweight Pattern)

    享元模式(Flyweight Pattern)主要用于减少创建的对象数量,并减少内存占用并提高性能. 这种类型的设计模式属于结构模式,因为该模式提供了减少对象计数的方法,从而改善应用的对象结构. 享元 ...

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

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  8. [设计模式] 11 享元模式 Flyweight

    转 http://blog.csdn.net/wuzhekai1985/article/details/6670298 问题 在面向对象系统的设计何实现中,创建对象是最为常见的操作.这里面就有一个问题 ...

  9. 七个结构模式之享元模式(Flyweight Pattern)

    定义: 运用共享技术对大量细粒度对象的复用,这要求这些对象都很相似,状态变化很小.将这些对象的内部状态和外部状态进行区分,对于内部状态相同的只存储一个对象,而对不同的外部状态则采用不同的操作. 结构图 ...

随机推荐

  1. safe close tcp connection

    https://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reli ...

  2. VSTO:C#获取文档控件的值

    基础知识准备: VSTO入门 创建Excel解决方案   string[] inputfileNames = { @"C:\1.xls", @"C:\2.xls" ...

  3. Network - Tips

    001 - 查询whois 可通过在线工具进行查询: https://www.whois365.com http://whois.aliyun.com http://whois.chinaz.com ...

  4. Python中Flask框架SQLALCHEMY_ECHO设置

    在用配置类的方式给app设置配置时, SQLALCHEMY_ECHO 这个是记录打印SQL语句用于调试的, 一般设置为False, 不然会在控制台输出一大堆的东西 /home/python/.virt ...

  5. psutil 跨平台根据程序名杀进程

    笔者在项目中遇到过需要根据进程名杀进程的需求,利用python库psutil实现了此功能. 模块地址: https://pypi.python.org/pypi/psutil/   psutil功能 ...

  6. [Umbraco] 创建第一个页面

    如何创建一个页面,很简单. 进入settings,首先右键点击“Document Types”, 在出现的菜单点击"Create",在弹出的窗口中 Master Document ...

  7. Python全局解释器锁 -- GIL

    首先强调背景: 1.GIL是什么?GIL的全称是Global Interpreter Lock(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定. 2.每个CPU在同一时间只能 ...

  8. (转)9 db2trc案例2(1,2)

    原文:http://book.51cto.com/art/200906/130068.htm 9.3.3  db2trc案例2(1) 在AIX操作系统上,系统原先运行良好,而后用户从DB2 V8 FP ...

  9. Python:高效计算大文件中的最长行的长度

    在操作某个很多进程都要频繁用到的大文件的时候,应该尽早释放文件资源(f.close()) 前2种方法主要用到了列表解析,性能稍差,而最后一种使用的时候生成器表达式,相比列表解析,更省内存 列表解析和生 ...

  10. 通过修改CR0寄存器绕过SSDT驱动保护

    为了安全起见,Windows XP及其以后的系统将一些重要的内存页设置为只读属性,这样就算有权力访问该表也不能随意对其修改,例如SSDT.IDT等.但这种方法很容易被绕过,我们只要将这些部分修改为可写 ...