JAVA SCRIPT设计模式--结构型--设计模式之FlyWeight享元模式(11)

Posted 火柴盒zhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA SCRIPT设计模式--结构型--设计模式之FlyWeight享元模式(11)相关的知识,希望对你有一定的参考价值。

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

        所有JAVA SCRIPT设计模式快捷连接:

              创建型:(1)  抽象工厂 (2) 生成器 (3) 工厂方法 (4) 原型  (5) 单例

              结构型:(6) 适配器  (7) 桥接  (8) 组合 (9) 装饰 (10) 外观 (11) 享元 (12) 代理​

              行为型:(13) ​职责链 (14) ​命令 (15) ​解释器 (16) ​迭代器 (17) ​中介者 (18) ​备忘录 (119) ​观察者 (20) ​状态​ (21) ​策略 (22) ​模板方法 (23) 访问者​


 一、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<this.rowchildrens.length;n++)
		
			let graphic=this.rowchildrens[n];
			let height=this.GetRowHeight(n);//假设算法
			context.y=height;
			graphic.Draw(context);
		
    
	AddRow(graphic) 
		this.rowchildrens.push(graphic);
		
	
	GetRowHeight(indexrow)
	
		let height=0;
		for(let n=0;n<=indexrow;n++)
		
			let graphic=this.rowchildrens[n];
			height=height+graphic.RowHeight;
		 
		return height;
	

   

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<this.childrens.length;n++)
		
			let graphic=this.childrens[n];
			context.x=n*30;//假设算法
			graphic.Draw(context);
		
    
	Add(graphic) 
		this.childrens.push(graphic);
	

   

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');//Glyph
		let bchar =flyweight.GetFlyweight('b');//Glyph
		let cchar =flyweight.GetFlyweight('c');//Glyph
		 
		let 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

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
 
 
 <script  type="module" >
 import Client  from './Client.js'; 
 var x=document.getElementById("mycanvas")
 var ctx=x.getContext("2d") //create 2d object
let cl=new Client();
cl.main(ctx)

 </script>
</head>
<body>
<canvas id="mycanvas" width=300px height=300px></canvas>
    
</body>
</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

以上是关于JAVA SCRIPT设计模式--结构型--设计模式之FlyWeight享元模式(11)的主要内容,如果未能解决你的问题,请参考以下文章

JAVA SCRIPT设计模式--结构型--设计模式之Decorator装饰模式

JAVA SCRIPT设计模式--结构型--设计模式之FACADE外观模式(10)

JAVA SCRIPT设计模式--结构型--设计模式之FACADE外观模式(10)

JAVA SCRIPT设计模式--结构型--设计模式之Proxy代理模式(12)

JAVA SCRIPT设计模式--结构型--设计模式之ADAPTER适配器

JAVA SCRIPT设计模式--结构型--设计模式之FlyWeight享元模式(11)