2022-02-04
分类:未分类
阅读(241)
Prototype-原型模式
-
原型模式: 通过原型的实例来指定创建对象的类型,然后通过拷贝来创建更多同类型的对象
-
原型模式的特点:
- 原型模式属于创建型模式
- 原型模式要求原型类实现拷贝自身的接口,这样就可以通过拷贝原型的实例来创建新的对象
- 原型模式拷贝原型实例创建的新对象不需要关心对象本身的类型,只需要实现原型实例拷贝自身的方法,就可以通过自定义的拷贝方法来创建新的对象,不需要通过new创建新的对象
原型模式的实现方式
- 原型模式主要用于对象的复制,核心就是抽象原型Prototype
- 抽象原型Prototype需要具备两个条件:
-
实现Clonable接口:
-
Clonable接口的作用是在运行时通知JVM可以安全地在实现Clonable接口的类上使用clone方法
- 在JVM中,只有实现了Clonable接口的类才可以拷贝,否则会抛出CloneNotSupportedException异常
-
重写Object类中的clone方法:
- 所有类的父类都是Object类 ,Object类中有clone() 方法用于返回一个拷贝的对象,但是方法的作用域是protected, 一般类无法进行调用
- 抽象原型Prototype将clone() 方法的作用域修改为public类型
-
原型模式的适用场景:
- 在需要重复创建相似的对象时可以使用原型模式,即只是个别的几个属性不同时
- 直接创建对象的成本损耗大.比如初始化时间长,CPU占用大,网络资源占用过多,需要优化资源等
- 直接创建一个对象后还需要准备大量的数据以及访问权限时,需要提高性能或者安全性
- 系统中大量使用该类对象,且各个调用者都需要给对象的属性重新赋值
-
原型模式有两种实现方式:
简单实现方式
- 原型模式的简单实现方式包含三个角色:
-
抽象原型Prototype: 抽象原型类.给出所有的具体原型所需要实现的拷贝方法的接口或者抽象类
-
具体原型ConcretePrototype: 用于拷贝的原型实例.实现了抽象原型Prototype所要求的接口
-
客户Client: 客户端Client用来请求创建新的对象
原型管理器实现方式
- 原型模式可以扩展成为带有原型管理器的原型模式:
- 在原型模式的基础上增加了新的原型管理器PrototypeManager类
- 原型管理器PrototypeManager类中使用HashMap保存多个复制的原型对象
- 客户端Client类可以通过原型管理器中的get(String id) 方法获取复制的原型对象
原型模式注意点
-
原型模式不会调用类的构造方法:
- 原型模式通过Object类的clone() 方法拷贝对象,是直接在内存中拷贝原型实例的数据,所以不会调用类的构造方法
- 类的构造方法不会执行并且访问权限对原型模式无效.因为单例模式中的将类的构造方法设置为private类型,但是clone() 方法是无视构造方法的权限的.因此原型模式是与单例模式相互冲突的,所以要特别注意原型模式不可以和单例模式一起使用
-
深拷贝与浅拷贝问题:
- 原型模式通过Object类的clone() 方法拷贝对象时只会拷贝对象的基本数据类型以及对应的封装类型和值类型的String类型,不会拷贝数组,容器对象,引用对象等.这就是浅拷贝
- 如果要实现深拷贝,需要将原型模式中的数组,容器对象和引用对象另行拷贝
原型模式总结
- 原型模式本省比较简单,易于实现.主要是重写Object中的clone() 方法,根据要求实现浅拷贝或者是深拷贝
- 原型模式的重点在浅拷贝和深拷贝的理解和运用
原型模式优点
-
使用原型模式创建对象比直接使用new创建对象的性能要好: 因为Object中的clone() 方法是一个本地native方法,直接操作内存中的二进制流.尤其在拷贝大对象时,性能提升明显
-
使用原型模式简化了对象的创建: 通过使用原型模式可以让对象的创建像复制粘贴一样简单
-
可以使用深拷贝的方式保存对象的状态: 通过使用原型模式拷贝对象,并将状态保存起来,可以简化对象的创建过程,以便在需要时使用,可以辅助实现撤销的操作
原型模式缺点
- 原型模式需要为每一个类配置一个clone() 方法
-
clone() 方法在每个类的内部,当对已有类进行重构时,需要修改代码,违背了开闭原则
- 实现深拷贝较为复杂,而且当对象之间存在多重嵌套时,为了实现深拷贝,需要每一层对象对应的类都必须支持深拷贝,实现比较复杂