• javascript设计模式学习之十五——装饰者模式


    一、装饰者模式定义

    装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象。这种为对象动态添加职责的方式就称为装饰者模式。装饰者对象和它所装饰的对象拥有一致的接口,对于用户来说是透明的。

    和java等语言不同的是,java的装饰器模式是给对象动态添加职责,javascript中,给对象添加职责的能力是与生俱来的,更侧重于给函数动态添加职责。

    二、java中的装饰者模式实现

    package com.bobo.shejimoshi.derector;
    
    public class Plane {
        public void fire(){
            System.out.println("发射普通子弹");
        }
    }
    package com.bobo.shejimoshi.derector;
    
    public class MissileDecorator {
        private Plane plane;
        public MissileDecorator(Plane plane){
            this.plane=plane;
    
        }
        
        public void fire(){
            plane.fire();
            System.out.println("发射导弹");
        }
    }

    可见在java等传统语言中,给对象动态增加职责的方式,并没有真正地改动对象自身,而是将对象放入另一个对象之中,这些对象都具有相同的对外接口。

    三、javascript中的装饰者模式实现

    3.1为javascript对象添加职责

    在javascript中,给对象添加职责是与生俱来的本领。同样是上面的例子,在javascript中可以这么实现: 

    //装饰者模式
        var plane={
            fire:function(){
                console.log("发射普通子弹");
            },
        };
        
        var missileDecorator=function(){
            console.log("发射导弹");
        };
        
        var fire1=plane.fire;
        plane.fire=function(){
            fire1();
            missileDecorator();
        };
        
        plane.fire();
         

    3.2为javascript函数添加职责

    为函数添加一些功能,在java等语言中貌似只能直接改写该函数,这显然违反了开放—封闭原则;

    如果不想更改原函数,可以像上面的例子,通过保存原函数引用的方式来改写某个函数,这种方式一种是需要借助中间变量保存原函数的引用,此外还会遇到this劫持的问题。

    因此,比较好的方式是利用AOP来进行函数装饰。

    Function.prototype.before

    Function.prototype.before=function(beforeFn){
            var _self=this;//保存原函数的引用
            return function(){
                beforeFn.apply(this,arguments);
                return _self.apply(this,arguments);
            };
        };
        
        document.getElementById=document.getElementById.before(function(){
            alert(1);
        });
        
        var sel=document.getElementById('colorSelect');

    如果想根据上一个函数的执行结果决定函数是否执行,甚至还可以这样写Function.prototype.before

    Function.prototype.before=function(beforeFn){
            var _self=this;
            return function(){
                if(beforeFn.apply(this,arguments)!==false){
                    _self.apply(this,arguments);
                }
            
            };
        };

    使用这种方法还可以动态改变函数的参数:

        var func=function(param){
            console.log(param);
        };
        func=func.before(function(param){       
            param.b='b';
        });
        func({'a':'a'});//输出 'a':a,'b':b

    Function.prototype.after

    Function.prototype.after=function(afterFn){
            var _self=this;
            return function(){
                var ret=_self.apply(this,arguments);
                afterFn.apply(this,arguments);
                return ret;
            };
        };
  • 相关阅读:
    canvas-绘制矩形-读书笔记
    获取页面路径中的参数
    微信小程序引用组件的方式
    this指向知识梳理
    for循环整理
    微信小程序使用wxs(小程序的一套脚本语言)
    textarea层级过高的解决办法
    防止用户连续点击按钮导致页面数据重复
    微信小程序tab切换
    HTML/CSS 知识点01 (转)
  • 原文地址:https://www.cnblogs.com/bobodeboke/p/5715147.html
Copyright © 2020-2023  润新知