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

享元抽象: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. 表单控件 css的三中引入方式css选择器

    1. 表单控件: 单选框 如果两个单选的name值一样,会产生互斥效果 <p> <!--单选框--> 男<input type="radio" nam ...

  2. ubuntu下wps无法使用搜狗输入法输入中文

    sudo vim /usr/bin/et sudo vim /usr/bin/wps sudo vim /usr/bin/wpp 以上三个文件,都加入如下内容后重新打开文档即可 export XMOD ...

  3. [ActionScript 3.0] as3处理xml的功能和遍历节点

    as3比as2处理xml的功能增强了N倍,获取或遍历节点非常之方便,类似于json对像的处理方式. XML 的一个强大功能是它能够通过文本字符的线性字符串提供复杂的嵌套数据.将数据加载到 XML 对象 ...

  4. Swift5 语言参考(六) 声明

    一个声明引入了一个新的名称或构建到你的程序.例如,您使用声明来引入函数和方法,引入变量和常量,以及定义枚举,结构,类和协议类型.您还可以使用声明来扩展现有命名类型的行为,并将符号导入到其他地方声明的程 ...

  5. 设置iptables NAT出外网

    有时候云上部署环境,不能动态自设路由,没有公网ip地址的服务器,只能通过NAT的方式出外网,下面就记录一下设置过程. 当前状态 服务器A只有一个内网IP,不能上外网,内网IP与服务器B内网相通:服务器 ...

  6. 1-1 Vue的介绍

    简单介绍Vue Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易 ...

  7. Ubutntu安装docker启动报Removed /etc/systemd/system/docker.service.

    Ubutntu安装docker启动报Removed /etc/systemd/system/docker.service.的错误,只需要执行以下三条命令. systemctl unmask docke ...

  8. cookie、session的区别

    相信你肯定经常听说cookie和Session,那你有没有好好了解这两个的区别呢?其实,不整理之前,我也是一脸懵. 为什么需要cookie和session呢?---因为Http是无状态的,web开发中 ...

  9. Java读取文件加锁代码Demo(利用Java的NIO)

    本博文部分转载于:http://blog.csdn.net/wangbaochu/article/details/48546717 Java 提供了文件锁FileLock类,利用这个类可以控制不同程序 ...

  10. 浏览器中F5和CTRL F5的行为区别及如何强制更新资源

    一.浏览器中F5和CTRL F5的行为区别 我们直接来看效果,下面是我打开qq网页,分别使用F5和CTRL F5,我们来看区别. F5: CTRL F5: 区别: 首先直观上的区别是CTRL F5明显 ...