zoukankan      html  css  js  c++  java
  • 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;
            };
        };
  • 相关阅读:
    mobx源码解读1
    表单元素之图形系
    koa2+koa-views示例
    avalon2的后端渲染实践
    向一个数组中插入元素
    一步步编写avalon组件02:分页组件
    avalon2学习教程15指令总结
    avalon2学习教程14动画使用
    WPF动态加载Menu菜单
    WPF自定义控件与样式 ---- 系列文章
  • 原文地址:https://www.cnblogs.com/bobodeboke/p/5715147.html
Copyright © 2011-2022 走看看