强制使用工厂

时间:2016-12-08 20:57:44

标签: javascript typescript ecmascript-6

我有一个课我需要一个简单的工厂方法:

class GTree{ 

    public static createNode(){ 
        return new GNode(); 
    } 

} 

这意味着我不想让消费者立即实例化GNode。

如何正确实施?

显然我不能这样做:

class GNode{
    constructor(){ 
        throw TypeError("This is nonsense"); 
    }
}

因为那时我根本无法创建节点 我如何强行使用工厂?

2 个答案:

答案 0 :(得分:2)

你无法在javascript中真正做到这一点,但你可以这样做:

export class GTree {
    public static createNode(name: string): GNode {
        return new GNodeImpl(name); 
    }
}

export interface GNode {
    name: string;
}

class GNodeImpl implements GNode {
    constructor(public name: string) {}
}

code in playground

仅导出GTreeGNode接口,这意味着无法从模块外部实例化GNodeImpl

我为示例添加了name属性。

答案 1 :(得分:2)

这是一个比我之前的评论更简单的方案。只需在私有(但共享)范围内定义GNode类,这样就可以调用构造函数的唯一位置,并重置.constructor属性,因此它不会漏出来了:



const GTree = (function() {
    class GNode {
        constructor() {

        }

        someOtherMethod() {
            console.log("someOtherMethod");
        }
    }
    // reset public .constructor
    GNode.prototype.constructor = function() {
        throw new Error("Can't call GNode constructor directly");
    };

    class GTree {
        constructor() {
            this.nodes = [];
        }

        createNode() {
            let node = new GNode();
            this.nodes.push(node);
            return node;
        }

        get length() {
            return this.nodes.length;
        }
    }
    return GTree;
})();


let tree = new GTree();
let node1 = tree.createNode();
let node2 = tree.createNode();
node1.someOtherMethod();
console.log(tree.length + " nodes");