在Javascript中使用Canvas时如何遵守demeter法则?

时间:2017-03-01 14:32:57

标签: javascript canvas dependency-injection law-of-demeter

假设我有这段代码:

function drawToCanvas() {
    const canvas = document.createElement('canvas');

    const context = canvas.getContext('2d');

    context.rect(10, 10, 100, 100);
    context.fill();

    const visibleCanvas = document.getElementById('mycanvas');
    const visibleContext = visibleCanvas.getContext('2d');

    visibleContext.drawImage(canvas, 0, 0);

    return visibleCanvas;
}

从LoD的角度来看,这个函数的第一部分基本上等同于

document.createElement('canvas').getContext('2d').rect(10, 10, 100, 100);

第二部分没有那么不同。

我应该如何使用依赖注入来防止这种情况,同时保留对画布及其上下文的引用?

2 个答案:

答案 0 :(得分:0)

LoD是指导方针,设计模式,而不是严格的规则。

但是如果你以不同的方式看待它,你不一定会使用这种技术违反LoD:

您使用画布并直接使用其ctx。在这种情况下,您将在类和画布返回的上下文之间创建关系。此时,你的上下文现在是一个直接的"邻居",虽然,是的,它在这里有点受骗。

您经常必须使用当前相关对象的子对象(如array.item.toString()),以避免为您要执行的每个任务创建不必要的集合。

与数据库规范化相同:这是一个有用的指导方针,可以让您保持正确的轨道,但有时您需要打破它以保持您的类结构和代码正常工作(在规范化的情况下,有时需要更好的性能,在物化视图中创建冗余或压缩数据。)

答案 1 :(得分:0)

(转发此处,因为我的评论空间不足。)

Euh,我不确定我是否理解正确,但是不会只使用canvas id的参数来满足LoD?由于画布的作用域是此函数,并且在这种情况下唯一的链接是参数('mycanvas'),因此您只能使用自己的函数参数。而且,如果您将上下文视为与画布不同的对象,因此.createElement().getContext().rect()违反了LoD,那么您只是遇到了很多麻烦。 Imho,任何内置的JS方法都不应该受到LoD的限制,因为重新记录它们自己对象中的所有内置函数,只是为了满足LoD,看起来过于冗长。

此外,JS不是严格的OOP,并且很多代码都是模块化和命名空间的。通常你无法避免,很多人甚至更喜欢做基本的JQuery链接:$('someSelector').find('someChild').attr('someChange');只要一个模块本身不会破坏关注点和单一责任(即使这个责任很大) ,就像创建/渲染一个完整的小部件一样,我个人不介意使用“快捷方式”,比如在模块中将不同对象的方法链接在一起。

如果你试图坚持所有模块的纯函数和清晰的公共接口,你会自动避免LoD在OOP环境中帮助防止的很多问题。

作为最后一点,在堆栈交换程序员或堆栈交换软件工程中,人们可能比JS部分更能帮助你,因为这比JS更广泛。