设计模式(十)享元模式Flyweight(结构型)

设计模式(十)享元模式Flyweight(结构型

说明:

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

1. 概述

面向对象技术可以很好地解决系统一些灵活性或可扩展性或抽象性的问题,但在很多情况下需要在系统中增加类和对象的个数。当对象数量太多时,将导致运行代价过高,带来性能下降等问题。比如:
例子1:图形应用中的图元等对象、字处理应用中的字符对象等。

2.解决方案:

          享元模式(Flyweight):对象结构型模式运用共享技术有效地支持大量细粒度的对象。

        它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。

4. 适用性

1)一个应用程序使用大量相同或者相似的对象,造成很大的存储开销。

2)对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。

3)如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。

4) 应用程序不依赖于对象标识。由于Flyweight对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

5)使用享元模式需要维护一个存储享元对象的享元池,而这需要耗费资源,因此,应当在多次重复使用享元对象时才值得使用享元模式

5.结构

6.构建模式的组成

1) 抽象享元类(Flyweight):描述一个接口,通过这个接口flyweight可以接受并作用于外部状态。
2) 具体享元类(ConcreteFlyweight):实现Flyweight接口 ,并为内部状态( 如果有的话 )增加存储空间 。ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的;即,它必须独立于ConcreteFlyweight对象的场景。
3) 非共享具体享元类(UnsharedConcreteFlyweight):— 并非所有的Flyweight子类都需要被共享。Flyweight接口使共享成为可能,但它并不强制共享。在Flyweight对象结构的某些层次,UnsharedConcreteFlyweight对象通常将ConcreteFlyweight对象作为子节点。
4) 享元工厂类(FlyweightFactory):创建并管理flyweight对象, 确保合理地共享flyweight。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象   flyweight的时候,享元工厂角色(Flyweight Factory对象)会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。
5)客户(Client):维持一个对flyweight的引用。计算或存储一个(多个)flyweight的外部状态。

7. 效果

享元模式的优点:

1)享元模式的优点在于它可以极大减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份。

2)享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。

享元模式的缺点:

1)享元模式使得系统更加复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。

2)为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。

8.实现

享元模式可以分成单纯享元模式和复合享元模式两种形式。

【单纯享元模式】

  在单纯的享元模式中,所有的享元对象都是可以共享的。

源代码:

[php] view
plain
 copy

 

 

  1. <?php  
  2.   
  3. /** 
  4.  * 单纯享元模式  
  5.  * @author guisu 
  6.  */  
  7.   
  8. /** 
  9.  * 抽象享元角色 
  10.  */  
  11. abstract class Flyweight {  
  12.   
  13.     /** 
  14.      * 示意性方法 
  15.      * @param string $state 外部状态 
  16.      */  
  17.     abstract public function operation($state);  
  18. }  
  19.   
  20. /** 
  21.  * 具体享元角色 
  22.  */  
  23. class ConcreteFlyweight extends Flyweight {  
  24.   
  25.     private $_intrinsicState = null;  
  26.   
  27.     /** 
  28.      * 构造方法 
  29.      * @param string $state  内部状态 
  30.      */  
  31.     public function __construct($state) {  
  32.         $this->_intrinsicState = $state;  
  33.     }  
  34.   
  35.     public function operation($state) {  
  36.         echo 'ConcreteFlyweight operation, Intrinsic State = ' . $this->_intrinsicState  
  37.         . ' Extrinsic State = ' . $state . '<br />';  
  38.     }  
  39.   
  40. }  
  41.   
  42.   
  43. /** 
  44.  * 享元工厂角色 
  45.  */  
  46. class FlyweightFactory {  
  47.   
  48.     private $_flyweights;  
  49.   
  50.     public function __construct() {  
  51.         $this->_flyweights = array();  
  52.     }  
  53.   
  54.     public function getFlyweigth($state) {  
  55.         if (isset($this->_flyweights[$state])) {  
  56.             return $this->_flyweights[$state];  
  57.         } else {  
  58.             return $this->_flyweights[$state] = new ConcreteFlyweight($state);  
  59.         }  
  60.     }  
  61.   
  62. }  
  63.   
  64. class Client{  
  65.     static function main (){  
  66.         $flyweightFactory = new FlyweightFactory();  
  67.         $flyweight = $flyweightFactory->getFlyweigth('state A');  
  68.         $flyweight->operation('other state A');  
  69.           
  70.         $flyweight = $flyweightFactory->getFlyweigth('state B');  
  71.         $flyweight->operation('other state B');  
  72.           
  73.     }  
  74. }  
  75.   
  76.   
  77.   
  78. ?>  

【复合享元模式】
复合享元模式对象是由一些单纯享元使用合成模式加以复合而成
复合享元角色所代表的对象是不可以共享的,但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。

[php] view
plain
 copy

 

 

  1. <?php  
  2.   
  3. /** 
  4.  * 复合享元模式 
  5.  *  
  6.  */  
  7.   
  8. /** 
  9.  * 抽象享元角色 
  10.  */  
  11. abstract class Flyweight {  
  12.   
  13.     /** 
  14.      * 示意性方法 
  15.      * @param string $state 外部状态 
  16.      */  
  17.     abstract public function operation($state);  
  18. }  
  19.   
  20. /** 
  21.  * 具体享元角色 
  22.  */  
  23. class ConcreteFlyweight extends Flyweight {  
  24.   
  25.     private $_intrinsicState = null;  
  26.   
  27.     /** 
  28.      * 构造方法 
  29.      * @param string $state  内部状态 
  30.      */  
  31.     public function __construct($state) {  
  32.         $this->_intrinsicState = $state;  
  33.     }  
  34.   
  35.     public function operation($state) {  
  36.         echo 'ConcreteFlyweight operation, Intrinsic State = ' . $this->_intrinsicState  
  37.         . ' Extrinsic State = ' . $state . '<br />';  
  38.     }  
  39.   
  40. }  
  41.   
  42. /** 
  43.  * 不共享的具体享元,客户端直接调用 
  44.  */  
  45. class UnsharedConcreteFlyweight extends Flyweight {  
  46.   
  47.     private $_flyweights;  
  48.   
  49.     /** 
  50.      * 构造方法 
  51.      * @param string $state  内部状态 
  52.      */  
  53.     public function __construct() {  
  54.         $this->_flyweights = array();  
  55.     }  
  56.   
  57.     public function operation($state) {  
  58.         foreach ($this->_flyweights as $flyweight) {  
  59.             $flyweight->operation($state);  
  60.         }  
  61.     }  
  62.   
  63.     public function add($state, Flyweight $flyweight) {  
  64.         $this->_flyweights[$state] = $flyweight;  
  65.     }  
  66.   
  67. }  
  68.   
  69. /** 
  70. * 享元工厂角色 
  71. */  
  72. class FlyweightFactory {  
  73.   
  74.     private $_flyweights;  
  75.   
  76.     public function __construct() {  
  77.         $this->_flyweights = array();  
  78.     }  
  79.   
  80.     public function getFlyweigth($state) {  
  81.         if (is_array($state)) { //  复合模式  
  82.             $uFlyweight = new UnsharedConcreteFlyweight();  
  83.   
  84.             foreach ($state as $row) {  
  85.                 $uFlyweight->add($row, $this->getFlyweigth($row));  
  86.             }  
  87.             return $uFlyweight;  
  88.         } else if (is_string($state)) {  
  89.             if (isset($this->_flyweights[$state])) {  
  90.                 return $this->_flyweights[$state];  
  91.             } else {  
  92.                 return $this->_flyweights[$state] = new ConcreteFlyweight($state);  
  93.             }  
  94.         } else {  
  95.             return null;  
  96.         }  
  97.     }  
  98.   
  99. }  
  100.   
  101. class Client{  
  102.     static function main (){  
  103.         $flyweightFactory = new FlyweightFactory();  
  104.         $flyweight = $flyweightFactory->getFlyweigth('state A');  
  105.         $flyweight->operation('other state A');  
  106.           
  107.         $flyweight = $flyweightFactory->getFlyweigth('state B');  
  108.         $flyweight->operation('other state B');  
  109.           
  110.         /* 复合对象*/  
  111.         $uflyweight = $flyweightFactory->getFlyweigth(array('state A', 'state B'));  
  112.         $uflyweight->operation('other state A');  
  113.   
  114.     }  
  115. }  
  116.   
  117.   
  118. ?>  

9.
与其他相关模式

客户端要引用享元对象,是通过工厂对象创建或者获得的,客户端每次引用一个享元对象,都是可以通过同一个工厂对象来引用所需要的享元对象。因此,可以将享元工厂设计成单例模式,这样就可以保证客户端只引用一个工厂实例。因为所有的享元对象都是由一个工厂对象统一管理的,所以在客户端没有必要引用多个工厂对象。不管是单纯享元模式还是复合享元模式中的享元工厂角色,都可以设计成为单例模式,对于结果是不会有任何影响的。

 
     Composite模式:Flyweight模式通常和Composite 模式结合起来,用共享叶结点的有向无环图实现一个逻辑上的层次结构。复合享元模式实际上是单纯享元模式与合成模式的组合。单纯享元对象可以作为树叶对象来讲,是可以共享的,而复合享元对象可以作为树枝对象, 因此在复合享元角色中可以添加聚集管理方法。通常,最好用Flyweight实现State
和Strategy 对象。

10.总结

1)  享元模式是一个考虑系统性能的设计模式,通过使用享元模式可以节约内存空间,提高系统的性能。 

2)  享元模式的核心在于享元工厂类,享元工厂类的作用在于提供一个用于存储享元对象的享元池,用户需要对象时,首先从享元池中获取,如果享 元池中不存在,则创       建一个新的享元对象返回给用户,并在享元池中保存该新增对象。

3)   享元模式以共享的方式高效地支持大量的细粒度对象,享元对象能做到共享的关键是区分内部状态(Internal State)和外部状态(External
State)。

       (1)   内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,因此内部状态可以共享。

       (2)   外部状态是随环境改变而改变的、不可以共享的状态。享元对象的外部状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候 再传入到享元对               象内部。一个外部状态与另一个外部状态之间是相互独立的。

时间: 2024-10-09 03:34:16

设计模式(十)享元模式Flyweight(结构型)的相关文章

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

原文:乐在其中设计模式(C#) - 享元模式(Flyweight Pattern)[索引页][源码下载] 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) 作者:webabcd 介绍 运用共享技术有效地支持大量细粒度的对象. 示例 有一个Message实体类,某些对象对它的操作有Insert()和Get()方法,现在要运用共享技术支持这些对象. MessageModel using System;using System.Collections.Generic;usi

【设计模式】—— 享元模式Flyweight

模式意图 享元模式,也叫[轻量级模式]或者[蝇量级模式].主要目的就是为了减少细粒度资源的消耗.比如,一个编辑器用到大量的字母数字和符号,但是不需要每次都创建一个字母对象,只需要把它放到某个地方共享使用,单独记录每次创建的使用上下文就可以了. 再比如餐馆的桌子,餐具,这些都是享元模式的体现.客户是流动的,每次吃饭都是用饭店固定的那些餐具,而饭店也不需要每次新来顾客,就买新的盘子餐具. 应用场景 1 一个系统应用到了大量的对象,而且很多都是重复的. 2 由于大量对象的使用,造成了存储效率上的开销.

C#设计模式(12)——享元模式(Flyweight Pattern)

原文:C#设计模式(12)--享元模式(Flyweight Pattern) 一.引言 在软件开发过程,如果我们需要重复使用某个对象的时候,如果我们重复地使用new创建这个对象的话,这样我们在内存就需要多次地去申请内存空间了,这样可能会出现内存使用越来越多的情况,这样的问题是非常严重,然而享元模式可以解决这个问题,下面具体看看享元模式是如何去解决这个问题的. 二.享元模式的详细介绍 在前面说了,享元模式可以解决上面的问题了,在介绍享元模式之前,让我们先要分析下如果去解决上面那个问题,上面的问题就

重温设计模式(一)——享元模式(Flyweight)

一.世间万物皆为对象 从大学校园中拦住一个软件工程专业的学生,问他,什么是面向对象.他会告诉你,世间万物皆是对象. 世界之大,何止万物.上至宇宙星辰,下至细菌病毒.皆为对象. 女孩,吐气如兰,仍留淡淡余香. 男孩,闭眼陶醉,不亦乐乎. 二.对象爆炸 呼吸之间,分子无数. 每个分子皆为一对象,恐万台服务器之矩阵亦无可容. 奈何乎? GOF 曰:享元模式! 三.何为享元模式 Flyweight : 次最轻量级的拳击选手.即粒度最小. 因此,享元模式的目的是采用共享技术解决大量细粒度对象的爆炸问题.

C++设计模式13----Flyweight享元模式

Flyweight享元模式概述 作用:运用共享技术有效地支持大量细粒度的对象. 内部状态intrinsic和外部状态extrinsic: 1)Flyweight模式中,最重要的是将对象分解成intrinsic和extrinsic两部分. 2)内部状态:在享元对象内部并且不会随环境改变而改变的共享部分,可以称为是享元对象的内部状态 3)外部状态:而随环境改变而改变的,取决于应用环境,或是实时数据,这些不可以共享的东西就是外部状态了. 4)内部状态和外部状态之间的区别: 在Flyweight模式应用

学习php设计模式 php实现享元模式(flyweight)_php技巧

一.意图运用共享技术有效的支持大量细粒度的对象 享元模式变化的是对象的存储开销二.享元模式结构图 三.享元模式中主要角色抽象享元(Flyweight)角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口.那些需要外蕴状态的操作可以通过调用商业以参数形式传入具体享元(ConcreteFlyweight)角色:实现Flyweight接口,并为内部状态(如果有的话)拉回存储空间.ConcreteFlyweight对象必须是可共享的.它所存储的状态必须是内部的不共享的具体享元(Unsh

设计模式:享元模式(Flyweight)

 运用共享技术有效地支持大量细粒度的对象.又名"蝇量模式".  在Java语言中,String类型就是使用了享元模式.String对象是final类型,对象一旦创建就不可改变.在JAVA中字符串常量都是存在常量池中的,Java会确保一个字符串常量在常量池中只有一个拷贝.譬如: String a = "abc"; String b = "abc"; System.out.println(a==b);  输出结果:true.这就说明了a和b量引用都指

.net设计模式实例之享元模式( Flyweight Pattern)

一.享元模式简介(Brief Introduction) 享元模式(Flyweight Pattern),运用共享技术有效支持大量细粒度的对象. Use sharing to support large numbers of fine-grained objects efficiently. 享元模式可以避免大量非常相似类的开销.在程序设计中有时需要生成大量细粒度的类 实例来表示数据.如果发现这些实例除了几个参数外基本伤都是相同的,有时就能够受大幅 度第减少需要实例化的类的数量.如果能把这些参数

Java设计模式之享元模式学习笔记

享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式.享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象. Java中String的实现就是一个典型的享元模式应用,Java中的String存在字符串常量池中,Java会确保一个字符串常量在常量池中只有一个拷贝.数据库连接池也是一个比较电信的享元模式应用,可简单理解为先初始化一定数量的数据库连接,