原型模式 Prototype

概述

原型模式的定义是用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。通俗一点讲就是拷贝一个新对象。

拷贝通常有浅拷贝和深拷贝,那么js中浅拷贝很容易实现,所以接下来主要用该模式实现深拷贝。

运用

原型模式的角色:

  • Prototype:抽象原型角色,抽象类或者接口,用来声明clone方法。
  • ConcretePrototype:具体的原型类,是客户端角色使用的对象,即被复制的对象。

Prototype 类

class Prototype {
    constructor(prototype) {
        console.log("Prototype Class created");
    }

    setFeature(key, val) {
        this[key] = val
    }

    clone() {
        throw new Error("This method must be overwritten!");
    }
}

ConcretePrototype 类

class ConcretePrototype1 extends Prototype {
    constructor() {
        super();
        console.log("ConcretePrototype1 created");
        this.feature = "feature 1"
    }

    // 实现深拷贝
    clone() {
        console.log('ConcretePrototype1.clone invoked');
        let clone = new ConcretePrototype1();
        let keys = Object.keys(this);

        keys.forEach(k => clone.setFeature(k, this[k]));

        console.log("ConcretePrototype1 cloned");
        return clone;
    }
}

class ConcretePrototype2 extends Prototype {
    constructor() {
        super();
        console.log("ConcretePrototype2 created");
        this.feature = "feature 2"
    }

    // 实现深拷贝
    clone() {
        console.log('ConcretePrototype2.Clone function');
        let clone = new ConcretePrototype2();
        let keys = Object.keys(this);

        keys.forEach(k => clone.setFeature(k, this[k]));
        console.log("ConcretePrototype2 cloned");
        return clone;
    }
}

上述 ConcretePrototype1 和 ConcretePrototype2 就是客户使用的普通对象,原型模式中让一个普通对象拷贝一个自己,仅需要继承 Prototype 类,重写 clone 方法即可。

测试一下

let proto1 = new ConcretePrototype1();
proto1.setFeature('feature', "feature 11");
let clone1 = proto1.clone();
console.log(clone1.feature);
console.log(typeof clone1);
console.log(clone1 === proto1);  // 深拷贝的对象与原对象不是同一个对象

# 输出如下结果:
# feature 11
# object
# false   

let proto2 = new ConcretePrototype2();
proto2.setFeature('feature', "feature 22");
let clone2 = proto2.clone();
console.log(clone2.feature);
console.log(typeof clone2);
console.log(clone2 === proto2);

# 输出如下结果:
# feature 22
# object
# false

总结

适用场景

  • 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。这个通常指浅拷贝。
  • 客户需要操作原对象,但又不希望操作影响到原对象,可以对原对象深拷贝出一个新对象来,然后在新对象上进行操作。

优点

  • 可以节省使用 new 初始化对象的复杂流程,因为可以完全拷贝一个已初始化好的对象

results matching ""

    No results matching ""