A fully initialized instance used for copying or cloning.

    JS 继承,不必多言。用原型实例指定创建对象的种类,并通过拷贝这些对象原型以创建新的对象。


    动机:通过拷贝子类的实例来创建新的对象。

    适用性:当一个系统应该独立于它的产品创建、构成和表示时,要使用 Prototype 模式。以及要实例化的类需要在运行的时候动态指定(JS 的本质)时;或者避免创建一个产品平行的类工厂层次时;一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们会比每次手工实例化类要方便一些。


    • 只为拷贝而存在。在一个对象之中定义一个函数,都是由引用创建,而不是拷贝创建,这样能够带来一定效率的提升。即用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
    • 用于创建其它对象的子类实例我们就将其叫做「原型」。
    • Object.create()方法可以用于复制对象。

    实现思路:

    • 使用一个原型管理器。当一个系统中的原型不固定的时候,我们就需要类似的管理器,以建立一个动态的「可用原型注册表」。
    • 实现克隆操作。
    1. class Node {
    2. insertElement();
    3. }
    4. class NodePrototype {
    5. private _node: Node;
    6. public clone() {
    7. return Object.create(this._node);
    8. };
    9. }
    10. class NodePrototypeManger {
    11. private _nodePrototypeMap: { [name: string]: NodePrototype };
    12. registerPrototype(node: NodePrototype);
    13. getPrototype(name: string): NodePrototype;
    14. }
    15. class Page {
    16. private _manager: NodePrototypeManager;
    17. createNodeList(tokens) {
    18. tokens.split(',').map(token => this.createNode(token));
    19. }
    20. createNode(token, modifiers) {
    21. if (token === 'A') {
    22. return modifiers ? Object.assign(this._manager.getPrototype('A').clone(), modifiers);
    23. }
    24. return this._manager.getPrototype('default').clone();
    25. }
    26. }

    效果:

    1. 运行的时候动态增加和删除产品。Prototype 允许只通过用户注册原型实例就可以将一个新的具体产品类并入系统。自然也就能够在运行态下动态添加或者删除原型。
    2. 改变值以指定新的对象。高度动态的系统。用户无需编程即可实现定义新的「类」,因为克隆一个原型类似于实例化一个类。
    3. 改变结构以指定新对象。结构上的深拷贝也能够形成不同结构的对象。比如:复合电路对象将 clone 实现为一个深拷贝,这样具有不同结构的电路也就成为了「原型」了。
    4. 减少子类构造。大大减少系统中所需要的类的个数
    5. 动类来动态配置应用。

    关联:

    • 大量使用 Composite 以及 Decorator 的设计模式可以从 Prototype 中获得好处。
    • Abstract Factory 可以存储一个被克隆的原型的集合,并且直接返回产品对象。