JAVA SCRIPT设计模式--结构型--设计模式之FlyWeight享元模式(11)
创始人
2024-03-26 02:12:55
0

        JAVA SCRIPT设计模式是本人根据GOF的设计模式写的博客记录。使用JAVA SCRIPT语言来实现主体功能,所以不可能像C++,JAVA等面向对象语言一样严谨,大部分程序都附上了JAVA SCRIPT代码,代码只是实现了设计模式的主体功能,不代表全部的正确,特此声明。若读者需要了解设计模式目录、原则、设计变化方向,环境相关等信息请查看设计模式开篇。
 


 一、UML类图

参与者:

1.1 Flyweight(Glyph)

  • 描述一个接口,通过这个接口flyweight可以接受并作用于外部状态

1.2 ConcreteFlyweight(Character) 

  • 实现Flyweight接口,并为内部状态(如果有的话)增加存储空间。ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的;即,它必须独立于ConcreteFlyweight对象的场景。

1.2 UnsharedConcreteFlyweight(Row,Column)

  • 并非所有的Flyweight子类都需要被共享。Flyweight接口使共享成为可能,但它并不强制共享。在Flyweight对象结构的某些层次,UnsharedConcreteFlyweight对象通常将ConcreteFlyweight对象作为子节点(Row和Column就是这样)。

1.2 FlyweightFactory

  • 创建并管理flyweight对象。
  • 确保合理地共享flyweight。当用户请求一个flyweight时,FlyweightFactory对象提供
  • 个已创建的实例或者创建一个(如果不存在的话)。

1.2 Client

  • 维持一个对flyweight的引用。
  • 计算或存储一个(多个)flyweight的外部状态。

二、意图

     运用共享技术有效地支持大量细粒度的对象。

三、适用性

  1. 一个应用程序使用了大量的对象。
  2.   完全由于使用大量的对象,造成很大的存储开销。
  3. 对象的大多数状态都可变为外部状态。
  4. 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
  5. 应用程序不依赖于对象标识。由于Flyweight对象可以被共享,对于概念上明显有别的对 象,标识测试将返回真值。

四、示例代码

4.1  动机

      Flyweight模式对那些通常因为数量太大而难以用对象来表示的概念或实体进行建模。例如,文档编辑器可以为字母表中的每一个字母创建一个flyweight。每个flyweight存储一个字符代码,但它在文档中的位置和排版风格可以在字符出现时由正文排版算法和使用的格式化命令决定。字符代码是内部状态,而其他的信息则是外部状态。

        逻辑上,文档中的给定字符每次出现都有一个对象与其对应,如下图所示。

 

         而这个对象出现在文档结构中的不同地方。 一个特定字符对象的每次出现都指向同一个实例,这个实例位于 flyweight对象的共享池中。

         表示字母“a”的flyweight只存储相应的字符代码;它不需要存储字符的位置或字体。用户提供与场景相关的信息,根据此信息flyweight绘出它自己。例如,Rowglyph知道它的子女应该在哪儿绘制自己才能保证它们是横向排列的。因此Rowglyph可以在绘制请求中向每一个子女传递它的位置。

        由于不同的字符对象数远小于文档中的字符数,因此,对象的总数远小于一个初次执行的程序所使用的对象数目。对于一个所有字符都使用同样的字体和颜色的文档而言,不管这个文档有多长,需要分配100个左右的字符对象(大约是ASCII字符集的数目)。由于大多数文档使用的字体颜色组合不超过10种,实际应用中这一数目不会明显增加。因此,对单个字符进行对象抽象是具有实际意义的

4.2  示例UML

目录结构:

4.2 Flyweight(Glyph)

  • 描述一个接口,通过这个接口flyweight可以接受并作用于外部状态
export default  class Glyph {ctx;constructor(ctx) {this.ctx=ctx;  }Draw(context) {   }add(graphic){}}

4.3 ConcreteFlyweight(Character) 

  • 实现Flyweight接口,并为内部状态(如果有的话)增加存储空间。ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的;即,它必须独立于ConcreteFlyweight对象的场景。
import Glyph  from '../Glyph.js';export default  class Character extends Glyph {char ;constructor(ctx) {super(ctx ); }Draw(context) {console.log(` Character Draw `+this.char);this.ctx.font=context.font;//"35px Arial";this.ctx.fillText(this.char,context.x,context.y);}SetChar(char){this.char=char;}} 

4.4 UnsharedConcreteFlyweight(Row,Column)

  • 并非所有的Flyweight子类都需要被共享。Flyweight接口使共享成为可能,但它并不强制共享。在Flyweight对象结构的某些层次,UnsharedConcreteFlyweight对象通常将ConcreteFlyweight对象作为子节点(Row和Column就是这样)。
import Glyph  from '../Glyph.js';export default  class Page extends Glyph {rowchildrens = [];constructor(ctx) {super(ctx ); }Draw(context) {console.log(` Page Draw `);for(let n=0;n

import Glyph  from '../Glyph.js';export default  class ROW extends Glyph {childrens = [];RowHeight=30;constructor(ctx) {super(ctx ); }Draw(context) {console.log(` ROW Draw `);for(let n=0;n

4.5 FlyweightFactory

  • 创建并管理flyweight对象。
  • 确保合理地共享flyweight。当用户请求一个flyweight时,FlyweightFactory对象提供
  • 个已创建的实例或者创建一个(如果不存在的话)。
import Character  from './Glyph/impl/Character.js';export default  class FlyweightFactory {charpool= new Map();ctx;constructor(ctx) {this.ctx=ctx; }GetFlyweight(key) {   if(this.charpool.has(key))return this.charpool.get(key);else{let onechar=new Character(this.ctx);onechar.SetChar(key);this.charpool.set(key,onechar);return onechar;}}}

4.6 Client

  • 维持一个对flyweight的引用。
  • 计算或存储一个(多个)flyweight的外部状态。
import FlyweightFactory  from './FlyweightFactory.js';
import Glyph  from './Glyph/Glyph.js';
import Character  from './Glyph/impl/Character.js';
import Page  from './Glyph/impl/Page.js';
import ROW  from './Glyph/impl/ROW.js';
import Contenxt  from './Context.js';export default class Client{main(ctx){let  flyweight =new FlyweightFactory(ctx);let achar =flyweight.GetFlyweight('a');//Glyphlet bchar =flyweight.GetFlyweight('b');//Glyphlet cchar =flyweight.GetFlyweight('c');//Glyphlet row1=new ROW(ctx);row1.Add(achar);row1.Add(bchar);let row2=new ROW(ctx);row2.Add(achar);row2.Add(cchar);let page=new Page(ctx);page.AddRow(row1);page.AddRow(row2);let contentx=new Contenxt("35px Arial",0,0,300,300);page.Draw(contentx);} }

4.7 测试HTML








测试结果:

Page.js:10  Page Draw 
ROW.js:10  ROW Draw 
Character.js:9  Character Draw a
Character.js:9  Character Draw b
ROW.js:10  ROW Draw 
Character.js:9  Character Draw a
Character.js:9  Character Draw c

五、源代码下载

        下载链接:https://pan.baidu.com/s/1XuPqp84cccBNVkbnMY3sKw 
         提取码:q2ut

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...