ES6组合模式下无需复制TextCell,如何扩展实现UnderlinedCell
嘿,你这个需求刚好戳中了ES6组合模式的精髓——不用继承链,用对象委托+组合来灵活扩展行为,完全不用复制整个对象!我来给你捋个清晰的实现思路:
首先,先假设你现有的TextCell是一个工厂函数(毕竟你用的是组合模式),大概长这样:
function TextCell(text) { return { getHeight() { return text.split("\n").length; }, draw(width, height) { const result = []; for (let i = 0; i < height; i++) { const line = text.split("\n")[i] || ""; result.push(line.padEnd(width)); } return result; } }; }
接下来要做的UnderlinedCell,核心思路是持有一个TextCell实例作为内部委托对象,只重写你需要修改的方法(getHeight和draw),其他行为直接委托给内部的TextCell,完全不用复制它的整个结构。
实现UnderlinedCell工厂函数
function UnderlinedCell(innerCell) { return { // 重写getHeight:原高度+1 getHeight() { return innerCell.getHeight() + 1; }, // 重写draw:先调用原cell的draw,再追加短横线行 draw(width, height) { // 注意这里要给原cell传height-1,因为我们要多一行下划线 const innerContent = innerCell.draw(width, height - 1); // 追加一行和宽度匹配的短横线 innerContent.push("-".repeat(width)); return innerContent; }, // 如果TextCell还有其他方法(比如getWidth),直接委托就行,不用重复写 getWidth() { return innerCell.getWidth(); } }; }
怎么用?
// 先创建一个普通TextCell const myText = TextCell("Hello\nES6组合模式"); // 用UnderlinedCell包装它 const underlinedText = UnderlinedCell(myText); // 测试getHeight:原TextCell是2行,所以返回3 console.log(underlinedText.getHeight()); // 输出 3 // 测试draw(宽度设为20) console.log(underlinedText.draw(20, 3)); // 输出结果: // ["Hello ", "ES6组合模式 ", "--------------------"]
为什么这种方式比Object.assign复制更好?
- 避免冗余复制:你不用把TextCell的所有方法都复制一遍,只是持有引用,内存更高效。
- 灵活的组合能力:以后你想加其他装饰(比如加边框、高亮),直接套多层工厂就行,完全不用改原对象结构。
- 行为同步:如果原TextCell的方法后续有更新,UnderlinedCell会自动继承这个变化(如果是用Object.assign复制的话,就会错过更新)。
当然,如果你的场景更倾向于不可变对象,也可以用Object.assign结合委托的思路,但上面这种委托方式是组合模式里最简洁高效的实现~
内容的提问来源于stack exchange,提问作者Stowoda
相关产品推荐
相关产品推荐

