《javascript设计模式与开发实践》读书笔记(5)

本周分享的是命令模式组合模式

命令模式

命令模式的意义在于将一个操作封装在一个命令对象中,从而将其四处传递。而JavaScript是将函数作为一等对象的语言,函数本身就可以四处传递,因此命令模式在JavaScript是天然实现的。但是就算这样,命令模式在JavaScript中仍然有期重要的意义,我们通过将某些操作封装在命令对象中,可以记录所有的历史操作,从而方便我们撤销重做**。下面我们看一个例子,我们实现一个canvas画线的功能,要求能撤销本次操作,并重复撤销的操作。canvas并不能删除元素,那canvas如何实现撤销的命令。其实我们可以记录,每次划线的参数,当需要撤销的时候,我们就清空画布,然后执行画线的的操作,直到当前操作之前。下面我们看代码,

var drawLineCommand = (function () {
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var drawer = {};
    drawer.drawLine = function (config) {
        ctx.beginPath();
        ctx.moveTo.apply(ctx, config.startPoint);
        ctx.lineTo.apply(ctx, config.endPoint);
        ctx.stroke();
    };
    function DrawLineCommand(reciver) {
        this.reciver = reciver;
        this.historyCommands = [];
        this.currentStep = 0;
    }

    DrawLineCommand.prototype.excute = function (config) {
        this.historyCommands.push(config);
        this.reciver.drawLine(config);
        this.currentStep = this.historyCommands.length - 1;
    };

    DrawLineCommand.prototype.undo = function () {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        var currentStep = this.currentStep;
        for (var i = 0; i < currentStep; i++) {
            this.excute(this.historyCommands[i]);
        }
        this.currentStep = currentStep - 1;
    };

    DrawLineCommand.prototype.redo = function () {
        var config = this.historyCommands[this.currentStep + 1];
        if (config) {
            this.excute(this.historyCommands[this.currentStep + 1]);
            this.currentStep++;
        }
    };

    return new DrawLineCommand(drawer);
})()

var config1 = {
    startPoint: [100, 100],
    endPoint: [200, 200]
};
var config2 = {
    startPoint: [200, 200],
    endPoint: [300, 200]
};
drawLineCommand.excute(config1);
drawLineCommand.excute(config2);
drawLineCommand.undo();
drawLineCommand.redo();

组合模式

组合模式将对像组成树形结构,组合模式的命令可以递归的执行下去。现在考虑这样的一个场景,我们用js定义了一个组件,这个组件有个render函数,通过render函数,这个组件就可以渲染在某个DOM元素上,同时这个组件还可以接受其它的一些组件,这些组件也有一个render函数。这样我们就可以得到一个组件树,当我们调用根组件的render函数的时候,整个组件树就会递归的调用render函数,直到整个树渲染出来。

(function () {
    function CircleComponent (config) {
        this.element = document.createElement('div');
        this.element.style.width = 2 * parseInt(config.radius, 10) + 'px';
        this.element.style.height = 2 * parseInt(config.radius, 10) + 'px';
        this.element.style.borderRadius = config.radius;
        this.element.style.backgroundColor = config.color;
    }

    CircleComponent.prototype.render = function (parent) {
        parent.appendChild(this.element);
    }

    function CirclesComponent (config) {
        this.element = document.createElement('div');
        console.log(this.element);
        this.children = [];
        for (var i = 0; i < config.number; i++) {
            j = i % config.radius.length;
            k = i % config.color.length;
            var secondConfig = {
                color: config.color[k],
                radius: config.radius[j]
            }
            this.children.push(new CircleComponent(secondConfig));
        }
    }

    CirclesComponent.prototype.render = function (parent) {
        var element = this.element;
        this.children.forEach(function(item) {
            item.render(element);
        });
        parent.appendChild(this.element);
    }
    var config = {
        number: 3,
        radius: ['100px'],
        color: ['#f00', '#0f0', '#0ff']
    };

    var circles = new CirclesComponent(config);
    circles.render(document.getElementById('circles'));
})()
#笔记##读书笔记##设计#
全部评论

相关推荐

07-01 13:37
门头沟学院 Java
steelhead:不是你的问题,这是社会的问题。
点赞 评论 收藏
分享
哈哈哈哈哈哈哈哈哈哈这个世界太美好了
凉风落木楚山秋:毕业出路老师不管,你盖个章他好交差就完事了,等你盖完毕业了就不关他事情了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务