# 原型模式
# 参考
# 定义
亦称,克隆、Clone、Prototype模式。由对象自身提供一个克隆方法,以对象作为原型,克隆方法能够返回一个相同或相似的新对象。
# 应用场景
对象属性并非总是外部可见的,如私有变量、不可枚举时,客户端难以甚至无法进行完整的对象复制。
客户端希望减少耦合,仅需要获得类的实例,无需知道对象所属类即可获取对象、克隆对象。
# 实现、应用思路
抽象原型接口、类:规定具体类必须实现clone方法。
具体原型类:能够实例化具体可复制的对象,实现clone方法。
访问(客户端)类:调用具体对象中的clone方法来复制对象。
原型模式的扩展,增加一个原型管理器 PrototypeManager 工厂类来中心化原型注册表,客户端通过搜索参数,比如简单的字符串,就能够获取原型对象,无需关注对象所属类,进一步减少耦合。
# 优点
可以克隆对象,而无须与所属具体类耦合。
克隆对象避免反复运行初始化代码。
方便生成复杂对象。
# 缺点
类需要增加clone方法,需要对已有类进行改造,违背开闭原则。
克隆循环引用的复杂对象需要小心处理,要意识到深、浅克隆的区别。
# 代码实例
// 抽象原型接口
abstract class Sharp {
abstract clone(): Sharp
}
// 具体原型类
class Circle extends Sharp {
radius: number
constructor(radius: number = 1) {
super()
this.radius = radius
}
clone() {
return new Circle(this.radius)
}
}
// 具体原型类
class Rectangle extends Sharp {
width: number
height: number
constructor(width: number = 1, height: number = 1) {
super()
this.width = width
this.height = height
}
clone() {
return new Rectangle(this.width, this.height)
}
}
type SharpTypes = 'circle' | 'rectangle'
type SharpMap = { [sharp in SharpTypes]: Sharp }
// 原型模式的扩展,中心化的原型管理、注册表类
class Manager {
sharpMap: SharpMap
constructor() {
this.sharpMap = {
circle: new Circle(),
rectangle: new Rectangle()
}
}
getSharp(type: SharpTypes) {
return this.sharpMap[type]
}
}
// 客户端类
class Application {
constructor() {
const circle1 = new Circle(5)
const circle2 = circle1.clone()
const circle3 = circle2.clone()
const rectangle1 = new Rectangle(2, 10)
const rectangle2 = rectangle1.clone()
console.log('circle1', circle1)
console.log('circle2', circle2)
console.log('circle3', circle3)
console.log('circle1 is equal to circle2 ->', circle1 === circle2)
console.log('circle2 is equal to circle3 ->', circle2 === circle3)
console.log('rectangle1', rectangle1)
console.log('rectangle2', rectangle2)
console.log(
'rectangle1 is equal to rectangle2 ->',
rectangle1 === rectangle2
)
const manager = new Manager()
const circleFromManager = manager.getSharp('circle')
const rectangleFromManager = manager.getSharp('rectangle')
console.log('circleFromManager', circleFromManager)
console.log('rectangleFromManager', rectangleFromManager)
}
}
new Application()