【发布时间】:2014-05-27 01:12:34
【问题描述】:
我有一个对象的树形结构,它们的属性对周围的对象有非常复杂的依赖关系,由它们在树中的位置决定。我已经硬编码了很多这些依赖项,并尝试创建某种更新循环(如果一个属性被更新,根据设计,所有依赖它的属性都会更新,并且以正确的顺序),但我想以更通用/抽象的方式处理它,而不是硬编码一堆对不同对象的更新调用。
假设,例如,我有 1 个超类和 3 个子类,然后是一个单独的容器对象。
形状
属性:parentContainer、index、left、top、width、height
方法:updateLeft()、updateTop()、updateWidth()、updateHeight()
Square 继承自 Shape
三角形继承自 Shape
Circle 继承自 Shape
ShapeContainer
属性:形状
方法:addShape(shape, index), removeShape(index)
我将给出一个伪代码示例更新方法来说明这些依赖项是如何出现的:
Square.updateTop() {
var prevShape = null;
if (this.index != 0) {
prevShape = this.parentContainer.shapes[this.index - 1];
}
var nextSquareInContainer = null;
for (var i = this.index; i < this.parentContainer.shapes.length; i++) {
var shape = this.parentContainer.shapes[i];
if(shape instanceof Square) {
nextSquareInContainer = shape;
break;
}
}
var top = 0;
if (prevShape != null && nextSquareInContainer != null) {
top = prevShape.top + nextSquareInContainer.width;
} else {
top = 22;
}
this.top = top;
}
因此,添加到 shapeConatiner 的任何正方形对象都将取决于前一个形状的顶部值以及容器宽度值中找到的下一个正方形的顶部值。
这里是一些设置示例形状容器的代码:
var shapeContainer = new ShapeContainer();
var triangle = new Triangle();
var circle = new Circle();
var square1 = new Square();
var square2 = new Square();
shapeContainer.addShape(triangle, 0);
shapeContainer.addShape(circle, 1);
shapeContainer.addShape(square1, 2);
shapeContainer.addShape(square2, 3);
所以,我想问题的症结在于,如果我更新上述圆的顶部值,我希望 square1 的顶部值能够自动更新(因为 square1 的顶部值和圆的顶部之间存在单向依赖关系价值)。所以我可以做到这一点的一种方法(我一直在做的方式,结合我的问题领域的一些其他特定知识来简化调用)是将类似于以下的代码添加到 Circle 的 updateTop 方法中(真的必须添加到每个形状的 updateTop 方法中):
Circle.updateTop() {
// Code to actually calculate and update Circle's top value, note this
// may depend on its own set of dependencies
var nextShape = this.parentContainer.shapes[this.index + 1];
if (nextShape instanceof Square) {
nextShape.updateTop();
}
}
这种类型的设计适用于对象之间的一些简单依赖关系,但我的项目有几十种类型的对象,它们的属性之间可能有数百个依赖关系。我是这样编码的,但是在尝试添加新功能或解决错误时很难推理。
是否存在某种设计模式来设置对象属性之间的依赖关系,然后当更新一个属性时,它会更新依赖它的其他对象上的所有属性(这可能会触发属性的进一步更新这取决于现在新更新的属性)?用于指定这些依赖项的某种声明性语法可能最适合可读性/可维护性。
另一个问题是,一个属性可能有多个依赖项,在我希望该属性自行更新之前,必须先更新所有依赖项。
我一直在研究 pub/sub 类型的解决方案,但我认为这是一个足够复杂的问题,需要寻求帮助。作为旁注,我正在使用 javascript。
【问题讨论】:
-
听起来你需要的是数据绑定。查看Addy Osmani's talk on Object.observe(),您还可以在其中找到一些可能可以解决您的问题的 polyfill。
标签: javascript algorithm oop design-patterns dependencies