面向对象设计模式_享元模式(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=;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)解读的更多相关文章
- 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern)
原文:乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) 作者:weba ...
- 设计模式-11享元模式(Flyweight Pattern)
1.模式动机 在面向对象程序设计过程中,有时会面临要创建大量相同或相似对象实例的问题.创建那么多的对象将会耗费很多的系统资源,它是系统性能提高的一个瓶颈. 享元模式就是把相同或相似对象的公共部分提取出 ...
- 二十四种设计模式:享元模式(Flyweight Pattern)
享元模式(Flyweight Pattern) 介绍运用共享技术有效地支持大量细粒度的对象. 示例有一个Message实体类,某些对象对它的操作有Insert()和Get()方法,现在要运用共享技术支 ...
- 【UE4 设计模式】享元模式 Flyweight Pattern
概述 描述 运用共享技术有效地支持大量细粒度对象的复用.系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用. 由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻 ...
- 设计模式系列之享元模式(Flyweight Pattern)——实现对象的复用
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- Java享元模式(Flyweight Pattern)
享元模式(Flyweight Pattern)主要用于减少创建的对象数量,并减少内存占用并提高性能. 这种类型的设计模式属于结构模式,因为该模式提供了减少对象计数的方法,从而改善应用的对象结构. 享元 ...
- 设计模式之享元模式(Flyweight)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- [设计模式] 11 享元模式 Flyweight
转 http://blog.csdn.net/wuzhekai1985/article/details/6670298 问题 在面向对象系统的设计何实现中,创建对象是最为常见的操作.这里面就有一个问题 ...
- 七个结构模式之享元模式(Flyweight Pattern)
定义: 运用共享技术对大量细粒度对象的复用,这要求这些对象都很相似,状态变化很小.将这些对象的内部状态和外部状态进行区分,对于内部状态相同的只存储一个对象,而对不同的外部状态则采用不同的操作. 结构图 ...
随机推荐
- java servlet编写验证码
import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.Buffere ...
- Android RecycleView 的优化
减少条目的 View 的层级.层级越少效率越高,尤其避免使用 weight.用 ConstraintLayout 可以最大程度减少层级. 使用 ViewStub.如果某个 view 可能不需要被加载, ...
- Android .9 图片
最初对 .9 图片不是十分理解,一些教程让人摸不到头脑. 最近重新研究终于明白了它的原理. 其实最重要的一点记住就可以了,就是 .9 图片的四条黑边的意义,每条黑边的意义都不一样: 顶部:在水平拉伸的 ...
- PHP程序员职业发展路线
重点:把LNMP搞熟练(核心是安装配置基本操作) 1.Linux: 基本命令.操作.启动.基本服务配置(包括rpm安装文件,各种服务配置等): 会写简单的shell脚本和awk/sed 脚本命令等. ...
- Python网络练习题
练习题 什么是C/S架构? C/S架构客户端.服务端架构,C/S端软件主要有网络游戏,QQ等 互联网协议是什么?分别介绍五层协议中每一层的功能? 互联网协议:计算机之间的通信标准 物理层:主要是基于电 ...
- [JavaWeb] Servlet Filter
作用: Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息. 可以将一个或多个 Servlet 过滤器附加到一个 Servlet 或一组 Servlet.Servle ...
- (转)Linux PS 详解
原文:https://cn.aliyun.com/jiaocheng/162702.html 摘要:原文地址:http://www.cnblogs.com/wangkangluo1/archive/2 ...
- webgl之3d动画
之前的几篇文章都是静态的,而这里主要介绍如何使物体动起来,并且学会使用性能监视器来监测性能. 而如果要让物体动起来,实际上我们是有两种方法的,第一种是让物体真的动起来,另外一种是让摄像机动起来这样物体 ...
- Git学习系列之CentOS上安装Git详细步骤(图文详解)
前言 最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑.不过,慢慢地有人把它移植到了Windows上.现在,Git可以在Linux.Unix.Mac和Win ...
- Go的方法集
方法集定义了接口的接受规则. package main import "fmt" type notifier interface { notify() } type user st ...