动机:采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行代价——主要指内存需求方面的代价。如何在避免大量细粒度对象问题的同 时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作?
意图:运用共享技术有效地支持大量细粒度的对象。

UML图解:

Flyweight模式现实中的应用:

1.现行的博客、企业、商务网站中其网站的代码本质上是一样的,不一样的只是具体的数据和模板而代码核心和数据库却是共享的;所以现行的做法是将每个用户的博客或网站整合到一个网站中,共享其相关的代码和数据,这样对于硬盘、内存、CPU、数据库空间等服务器资源都可以达成共享,减少服务器资源的浪费,而对于代码,由于是一份实例,维护和扩展都更加容易;
2.再比如,.NET下字符串string 对象的也是运用了Flyweight模式,string a="享元设计模式";string b="享元设计模式";Object.ReferenceEquals(a,b);返回结果是true;
3.像围棋、五子棋、跳棋等等,它们都有大量的棋子对象,而它们的内部状态(如颜色,大小)都是恒定的; 而外部状态(坐标)却是变化的,就围棋而论,一盘棋理论上有361个空位可以放棋子,如果用常规的面向对象方式编程,每盘棋可能有两三百个棋子对象产生,一台服务器就很难支持更多的玩家玩围棋游戏了,所以,现行的设计是采用享元设计模式解决这种服务器空间有限问题,采用此设计模式至少棋子对象可以减少到只有两个实例。

示例:以五子棋游戏为例;代码如下

namespace Flyweight
{
/// <summary>
/// 抽象棋子类
/// </summary>
public abstract class Chess
{
Color color;
public string nickName { get; set; } /// <summary>
/// 棋子颜色
/// </summary>
public Color Color
{
get { return color; }
} /// <summary>
/// 棋子名称
/// </summary>
public string NickName
{
get { return nickName; }
} protected Chess(Color c, string nickname)
{
color = c;
nickName = nickname;
} /// <summary>
/// 在棋盘上画出自身
/// </summary>
/// <param name="p"></param>
/// <param name="radius"></param>
public abstract void Draw(Point p, int radius); } /// <summary>
/// 五子棋
/// </summary>
public class FiveChess:Chess
{
public FiveChess(Color c,string name)
: base(c, name)
{ } public override void Draw(Point p, int radius)
{
//画五子棋代码实现....
}
} /// <summary>
/// 生产五子棋棋子工厂类
/// </summary>
public static class FiveChessFactory
{
private static Hashtable chessTable = new Hashtable(); public static Chess GetChess(Color key)
{
if (!chessTable.ContainsKey(key))
{
chessTable.Add(key, new FiveChess(key,key.Name+"方"));
}
return (Chess)chessTable[key];
}
} /// <summary>
/// 客户程序
/// </summary>
public class FiveChessGame
{
public static void Main()
{
//红方VS黑方 可以将坐标位置用两个集合来储存,用来判断输赢
FiveChessFactory.GetChess(Color.Red).Draw(new Point(5, 5), 3);
FiveChessFactory.GetChess(Color.Black).Draw(new Point(5, 10), 3); FiveChessFactory.GetChess(Color.Red).Draw(new Point(5, 0), 3);
FiveChessFactory.GetChess(Color.Black).Draw(new Point(5,15 ), 3); FiveChessFactory.GetChess(Color.Red).Draw(new Point(10,5 ), 3);
FiveChessFactory.GetChess(Color.Black).Draw(new Point(20, 5), 3);
//这样无论红方和黑方下多少棋子,只有红棋子和黑棋子两个具体实例对象,大大降低了系统的消耗 }
}
}

Flyweight模式的几个要点:

1、面向对象很好滴解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight设计模式主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。
2、Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体 实现方面,要注意对象状态的处理
3、对象的数量太大从而导致对象内存开销大——什么样的数量才算大?这需要我们仔细的根据具体应用情况进行评估,而不能凭空臆断

面向对象设计模式之Flyweight享元模式(结构型)的更多相关文章

  1. 设计模式(11)--Flyweight(享元模式)--结构型

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.模式定义: 享元模式是对象的结构模式.享元模式以共享的方式高效地支持大量的细粒度对象. 2.模式特点: 享元模 ...

  2. Flyweight享元模式(结构型模式)

    1.面向对象的缺点 虽然OOP能很好的解决系统抽象的问题,并且在大多数的情况下,也不会损失系统的性能.但是在某些特殊的业务下,由于对象的数量太多,采用面向对象会给系统带来难以承受的内存开销.示例代码如 ...

  3. 设计模式(十二): Flyweight享元模式 -- 结构型模式

    说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...

  4. 设计模式之flyweight享元模式

    运用共享技术支持大量细粒度对象的使用 Flyweight模式(享元) Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模 ...

  5. Flyweight 享元(结构型)

    一:描述:(该模式实际应用较少) Flyweight 享元模式是对大量细粒度的元素进行共享和重用.减少对象的创建减轻内存: 注和单例模式不同的是:享元模式的各个对象佣有各自的行为并可实例化,单例模式的 ...

  6. Java设计模式:Flyweight(享元)模式

    概念定义 享元(Flyweight)模式运用共享技术高效地支持大量细粒度对象的复用. 当系统中存在大量相似或相同的对象时,有可能会造成内存溢出等问题.享元模式尝试重用现有的同类对象,如果未找到匹配的对 ...

  7. go语言设计模式之Flyweight(享元模式)

    flyweight.go package flyweight import ( "time" ) const ( TEAM_A = "A" TEAB_B = & ...

  8. 设计模式11: Flyweight 享元模式(结构型模式)

    Flyweight 享元模式(结构型模式) 面向对象的代价 面向对象很好的解决了系统抽象性的问题,同时在大多数情况下也不会损及系统的性能.但是,在某些特殊应用中,由于对象的数量太大,采用面向对象会给系 ...

  9. C++设计模式-Flyweight享元模式

    Flyweight享元模式 作用:运用共享技术有效地支持大量细粒度的对象. 内部状态intrinsic和外部状态extrinsic: 1)Flyweight模式中,最重要的是将对象分解成intrins ...

随机推荐

  1. 数据结构(树,点分治):POJ 1741 Tree

      Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). D ...

  2. HDOJ 2014 青年歌手大奖赛_评委会打分

    Problem Description 青年歌手大奖赛中,评委会给参赛选手打分.选手得分规则为去掉一个最高分和一个最低分,然后计算平均得分,请编程输出某选手的得分. Input 输入数据有多组,每组占 ...

  3. 在C#中internal关键字是什么意思?

    这个回答的很不错 :http://zhidao.baidu.com/link?url=BGmYomZnf_-94L4uPXa-gzYMssL5HGmZyk_fFG7x4i4z_vL8qN3o7CrJg ...

  4. bzoj 1560 [JSOI2009]火星藏宝图(DP)

    1560: [JSOI2009]火星藏宝图 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 647  Solved: 309[Submit][Status ...

  5. lightoj 1005 组合数学

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1005 #include <cstdio> #include <cst ...

  6. php 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法

    php 获取今日.昨日.上周.本月的起始时间戳和结束时间戳的方法,主要使用到了 php 的时间函数 mktime.下面首先还是直奔主题以示例说明如何使用 mktime 获取今日.昨日.上周.本月的起始 ...

  7. 遇到的retain cycle例子

    retain cycle 会造成内存溢出,严重情况会引起崩溃.一般注意点也不会发生,但在网络连接比较多的地方就会不小心出现,vc异步的网络请求,成功后的block调用vc,如果此时,用户已经不用此vc ...

  8. 批量更新数据小心SQL触发器的陷阱

    批量更新数据时候,Inserted和Deleted临时表也是批量的,但触发器只会调用执行一次!两个概念千万不要弄混淆! 错误的理解:例如:创建在A表上创建了一个Update触发器,里面写的是Updat ...

  9. PHP简单利用token防止表单重复提交(转)

    <?php/* * PHP简单利用token防止表单重复提交 */function set_token() { $_SESSION['token'] = md5(microtime(true)) ...

  10. Linux下得到显示屏参数的方法

    先安装一个软件,然后使用权ddcprobe可以查看当前支持的分辨率和刷新频率#sudo apt-get install xresprobe运行 #sudo ddcprobe会得到下面的信息vbe: V ...