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

享元抽象: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. hash的安全性

    在区块链中,我们面临着两个问题: 隐私问题 快速对账问题 由于区块链中,每个人都存在着一个账本,当一个人有收入的时候,将会进行广播到所有人的账本,例如张三收入xxx钱,这样子所有的账本才能同步更新.但 ...

  2. Ubuntu系统常见问题解决

    我本人使用Ubuntu16.04LTS已经有一段时间了.实话来说,ubuntu虽然确实是开源世界的一款优秀的桌面操作系统,但是易用性和稳定性相比Windows还是差太多.本人从安装系统到逐步配置生产环 ...

  3. Django(视图 CBV、FBV)

    day67 参考:http://www.cnblogs.com/liwenzhou/articles/8305104.html CBV和FBV 我们之前写过的都是基于函数的view,就叫FBV.还可以 ...

  4. mongoose 基础api 图表整理

    一.背景 今天看 mongoose 的基础 API,参考了下面的链接做了图表以供查阅. 参考资料: http://www.cnblogs.com/xiaohuochai/p/7215067.html ...

  5. 虚拟机安装centos7

    主要参考这个文档(我已经把网页保存到本地了): http://www.bkjia.com/Linuxjc/867013.html 主要注意: 1.虚拟机网络我选择的桥接模式,在CentOS安装时打开这 ...

  6. javascript之快速排序

    快速排序思想其实还是挺简单的,分三步走: 1.在数组中找到基准点,其他数与之比较. 2.建立两个数组,小于基准点的数存储在左边数组,大于基准点的数存储在右边数组. 3.拼接数组,然后左边数组与右边数组 ...

  7. 解决Navicat Premium终端操作mysql ONLY_FULL_GROUP_BY错误

    解决navicate终端操作mysql ONLY_FULL_GROUP_BY错误     问题描述: [Err] 1055 - Expression #1 of SELECT list is not ...

  8. 七、Framework类库

    1.Framework类库简介 .Net Framework类库包含Framework类库(Framework Class Library,FCL).FCL是一组DLL程序集的统称,其中含有数千个类型 ...

  9. Openstack单元测试工具简单说明

    一.Openstack 的单元测试工具介绍 1.unittest unittest: 是 Python 的标准库,提供了最基本的单元测试功能,包括 单元测试运行器(简称runner) 和 单元测试框架 ...

  10. javascript中对条件判断语句的优化 分类: JavaScript 2015-06-07 09:54 832人阅读 评论(2) 收藏

    不管写什么程序,平时都会用到条件语句,如:if...else... switch这样的语句,来达到对条件的判断.下面看来一段代码: function abc(test){ if (test == 1) ...