共计 2111 个字符,预计需要花费 6 分钟才能阅读完成。
相熟 JavaScript
的同学对于原型的概念可能并不生疏,明天要说的原型模式和这个差不多是相似的,然而还是存在一些不同。原型模式的核心思想是,通过拷贝指定的 原型实例 (对象)
,创立跟该对象一样的新对象。简略了解就是 克隆指定对象
。
所有的原型类都必须有一个通用的接口,使得即便在对象所属的具体类未知的状况下也能复制对象。原型对象能够生成本身的残缺正本,因为雷同类的对象能够互相拜访对方的公有成员变量。
什么是原型模式
原型模式:用原型实例指定创建对象的品种,并且通过拷贝这些原型创立新的对象。—— 节选自百度百科
如果你有一个对象,并心愿生成与其完全相同的一个复制品,你该如何实现呢?首先,你必须新建一个属于雷同类的对象。而后,你必须遍历原始对象的所有成员变量,并将成员变量值复制到新对象中。
原型模式用一个曾经创立的实例作为原型,通过复制该原型对象来创立一个和原型雷同或者类似的新对象。在这里,原型实例指定了要创立的对象的品种。用这种形式创建对象十分搞笑,基本无需晓得对象创立的细节。比方咱们作为程序员常常应用复制粘贴大略就是这个情理。
然而间接复制还有另外一个问题。因为你必须晓得对象所属的类能力创立复制品,所以代码必须依赖该类。即便你能够承受额定的依赖性,那还有另外一个问题:有时你只晓得对象所实现的接口,而不晓得其所属的具体类,比方可向办法的某个参数传入实现了某个接口的任何对象。
原型模式将克隆过程委派给被克隆的理论对象。模式为所有反对克隆的对象申明了一个通用接口,该接口让你可能克隆对象,同时又无需将代码和对象所属类耦合。通常状况下,这样的接口中仅蕴含一个 克隆办法。
所有的类对 克隆办法的实现都十分类似。该办法会创立一个以后类的对象,而后将原始对象所有的成员变量值复制到新建的类中。你甚至能够复制公有成员变量,因为绝大部分编程语言都容许对象拜访其同类对象的公有成员变量。
原型模式优缺点
原型模式是一种创立型设计模式,原型模式容许一个对象再创立另外一个可定制的对象,基本无需晓得任何如何创立的细节, 工作原理是: 通过将一个原型对象传给那个要动员创立的对象,这个要动员创立的对象通过申请原型对象拷贝它们本人来施行创立。
如果子类的区别仅在于其对象的初始化形式,那么你能够应用该模式来缩小子类的数量。他人创立这些子类的目标可能是为了创立特定类型的对象。如果你须要复制一些对象,同时又心愿代码独立于这些对象所属的具体类,能够应用原型模式。原型模式为客户端代码提供一个通用接口,客户端代码可通过这一接口与所有实现了克隆的对象进行交互,它也使得客户端代码与其所克隆的对象具体类独立开来。
长处
- 简化创立新对象的过程并提高效率
- 可动静获取对象运行时的状态
- 原始对象变动相应克隆对象也会发生变化
毛病
- 对已有类批改时,须要批改源码,违反了开闭准则
- 须要为每一个类都配置一个
clone
办法 - 当实现深拷贝时,须要编写较为简单的代码,并且当对象之间存在多层嵌套的援用时,为了实现深拷贝,每一层对象对象的类都必须反对深拷贝,实现起来比拟麻烦,减少了程序的复杂程度
示例
原型模式的次要角色如下:
- 原型:接口将克隆办法进行申明。在绝大多数状况下,其中只会有一个名为
clone
的办法 - 具体原型:类将实现克隆办法。除了将原始对象的数据复制到克隆体中之外,该办法有时还需解决克隆过程中的极其状况,例如克隆关联对象和梳理递归依赖等等
- 客户端:能够复制实现了原型接口的任何对象
类图如下所示:
代码示例:
interface Prototype {clone():Prototype;
}
class Dog implements Prototype {
public name: string;
public birthYear: number;
public sex: string;
public presentYear: number;
constructor() {
this.name = "lili";
this.birthYear = 2015;
this.sex = "男";
this.presentYear = 2018;
}
public getDiscription(): string {return ` 狗狗叫 ${this.name},
性别 ${this.sex},
${this.presentYear}年,
${this.presentYear-this.birthYear}岁了 `;
}
// 实现复制
public clone(): Prototype {return Object.create(this);
}
}
// 应用
const dog = new Dog();
console.log(dog.getDiscription());
dog.presentYear = 2020;
const dog1 = Object.create(dog);
console.log(dog1.getDiscription());
总结
原型并不基于继承,因而没有继承的毛病。另一方面,原型须要对被复制对象进行简单的初始化。工厂办法基于继承,然而它不须要初始化步骤。有时候原型能够作为备忘录模式的一个简化版本,其条件是你须要在历史记录中存储的对象的状态比较简单,不须要链接其余内部资源,或者链接能够不便地重建。