JAVA SCRIPT设计模式是本人根据GOF的设计模式写的博客记录。使用JAVA SCRIPT语言来实现主体功能,所以不可能像C++,JAVA等面向对象语言一样严谨,大部分程序都附上了JAVA SCRIPT代码,代码只是实现了设计模式的主体功能,不代表全部的正确,特此声明。若读者需要了解设计模式目录、原则、设计变化方向,环境相关等信息请查看设计模式开篇。
参与者:
为其他对象提供一种代理以控制对这个对象的访问。
对一个对象进行访问控制的一个原因是为了只有在我们确实需要这个对象时才对它进行创建和初始化。我们考虑一个可以在文档中嵌入图形对象的文档编辑器。有些图形对象的创建开销很大。但是打开文档必须很迅速,因此我们在打开文档时应避免 一次性创建所有开销很大的对象。因为并非所有这些对象在文档中都同时可见,所以也没有必要同时创建这些对象。
这一限制条件意味着,对于每一个开销很大的对象,应该根据需要进行创建,当一个图像变为可见时会产生这样的需要。但是在文档中我们用什么来代替这个图像呢?我们又如何才能隐藏根据需要创建图像这一事实,从而不会使得编辑器的实现复杂化呢?例如,这种优化不应影响绘制和格式化的代码。
问题的解决方案是使用另一个对象,即图像 Proxy,替代那个真正的图像。 Proxy可以代替一个图像对象,并且在需要时负责实例化这个图像对象。
只有当文档编辑器激活图像代理的Draw操作以显示这个图像的时候,图像Proxy才创建真 正的图像。Proxy直接将随后的请求转发给这个图像对象。
目录结构:
import Graphic from '../Graphic.js';
import MyImage from './MyImage.js';
export default class ImageProxy extends Graphic {fileName;extent;image;//被代理的js Image对象constructor(ctx,fileName,extent) {super(ctx ); this.fileName=fileName;this.extent=extent;}Draw() {if(this.image==null){console.log(` 图片Draw代理第一次被实际调用 `);this.LoadImage();}else{console.log(` 图片Draw已经被初始化后调用 `);return this.image.Draw();}}GetExtent(){if(this.image==null){console.log(` 获取图片的大小 ,用于计算站位空间`);return this.extent;}return this.image.GetExtent();}LoadImage(){this.image=new MyImage(this.ctx,this.fileName);this.image.Load();}}
export default class Graphic {ctx;constructor(ctx) {this.ctx=ctx; }Draw() { }GetExtent(){}Store(){}Load(){}}
import Graphic from '../Graphic.js';export default class MyImage extends Graphic {fileName;image;//被代理的js Image对象constructor(ctx,fileName) {super(ctx ); this.fileName=fileName; }Draw() {console.log(` 图片被画到画布上 `);this.ctx.drawImage(this.image,0,0); }GetExtent(){return {height:this.image.height,width:this.image.width} ;}async Load(){console.log(` 图片加载。。。 `);this.image =new Image();this.image.src = this.fileName;this.image.onload=() => { this.Draw();} }}
import ImageProxy from './Graphic/impl/ImageProxy.js';
export default class Client{main(ctx){let imageProxy =new ImageProxy(ctx,'./hb.jpg',{height:950,width:1200});/**从代理获取图片大小**/console.log(` 第一次调用: 图片Draw `);imageProxy.GetExtent();imageProxy.Draw();/**模拟等待三秒后,实际调用**/setTimeout(() => { console.log(` 第二次调用:图片Draw `);imageProxy.GetExtent();imageProxy.Draw();} , 3000 )} }
测试结果:
Client.js:7 第一次调用: 图片Draw
ImageProxy.js:26 获取图片的大小 ,用于计算站位空间
ImageProxy.js:15 图片Draw代理第一次被实际调用
MyImage.js:21 图片加载。。。
MyImage.js:12 图片被画到画布上
Client.js:13 第二次调用:图片Draw
ImageProxy.js:18 图片Draw已经被初始化后调用
MyImage.js:12 图片被画到画布上
下载链接:https://pan.baidu.com/s/1XuPqp84cccBNVkbnMY3sKw
提取码:q2ut