代理模式(Proxy Pattern)

用一个新的类来代理另一个类,这种模式一般用于方法的前置操作或拦截。

代理模式的实例

现有一个类在初始化的时候会装载磁盘,再调用display按钮展示文件。

  1. class RealImage {
  2. constructor(fileName){
  3. this.fileName = fileName;
  4. this.loadFromDisk(fileName);
  5. }
  6. display() {
  7. console.log("Displaying " + this.fileName);
  8. }
  9. loadFromDisk(fileName){
  10. console.log("Loading " + fileName);
  11. }
  12. }

但我不想这样,我希望初始化不载入文件,而是在display的时候,如果发现没有载入就载入,如果载入了那就直接展示,那么我们要怎么做呢?

这个时候我们可以用一个类来代理这个类的行为。

  1. class ProxyImage {
  2. constructor(fileName){
  3. this.fileName = fileName;
  4. }
  5. display() {
  6. if(this.realImage == null){
  7. this.realImage = new RealImage(this.fileName);
  8. }
  9. this.realImage.display();
  10. }
  11. }

那么我们在使用的时候就可以不改变原来的类,而实现一些不一样的功能

  1. const image = new ProxyImage("test_10mb.jpg");
  2. console.log('not use es6 Proxy:')
  3. // 图像将从磁盘加载
  4. image.display();
  5. console.log('')
  6. // 图像不需要从磁盘加载
  7. image.display();
  8. /**
  9. * output:
  10. * not use es6 Proxy:
  11. * Loading test_10mb.jpg
  12. * Displaying test_10mb.jpg
  13. *
  14. * Displaying test_10mb.jpg
  15. */

当然用最新的ES6也提供了代理的功能,就不细说了,有兴趣可以看以下

  1. const ProxyImageEs6 = new Proxy(RealImage,{
  2. construct: function(target, args) {
  3. let imageObj = {};
  4. imageObj.__proto__ = target.prototype;
  5. imageObj.fileName = args[0];
  6. return new Proxy(imageObj,{
  7. get: function (target, key, receiver) {
  8. if(key=='display') {
  9. return ()=>{
  10. if(this.realImage == null){
  11. this.realImage = new RealImage(target.fileName);
  12. }
  13. this.realImage.display();
  14. };
  15. }
  16. return Reflect.get(target, key, receiver);
  17. },
  18. });
  19. }
  20. })
  21. console.log('\n\nuse es6 Proxy:')
  22. const imageEs6 = new ProxyImageEs6("test_10mb.jpg");
  23. // 图像将从磁盘加载
  24. imageEs6.display();
  25. console.log('')
  26. // 图像不需要从磁盘加载
  27. imageEs6.display();
  28. /**
  29. * output:
  30. * use es6 Proxy:
  31. * Loading test_10mb.jpg
  32. * Displaying test_10mb.jpg
  33. *
  34. * Displaying test_10mb.jpg
  35. */

代理模式的优势

能在不改变原有类的情况下,实现一些功能或者实现拦截和一些前置操作。

上一页(享元模式)

下一页(责任链模式)