目录
二、原型模式
1、概述
2、应用场景
3、优缺点
优点
缺点
4、主要角色
5、深克隆与浅克隆
深克隆
浅克隆
6、通过Cloneable接口实现浅克隆
实体类
测试类
运行结果
7、改良5
实体类
测试类
运行结果
8、原型管理器
概述
功能类
测试类
运行结果
二、原型模式
第二次梳理:原型模式的目的是在创建多个同一个类的相同或相似对象(属性等完全相同,或者稍有不同)时提高效率,直接对原有对象进行复制,若有个别属性的不同再对个别属性进行修改即可!浅克隆(浅拷贝)就是克隆的时候只克隆基本数据类型的属性,对象克隆的是内存地址,深克隆(深拷贝)克隆所有数据!原型管理器是对多个被克隆对象的集中管理,以方便克隆!时间:2021年05月13日 09点23分40秒
1、概述
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
2、应用场景
- 对象之间相同或相似,即只是个别的几个属性不同的时候;
- 创建对象成本较大,例如初始化时间长,占用CPU太多,或者占用网络资源太多等,需要优化资源;
- 创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性;
- 系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值;
3、优缺点
优点
- Java自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良;
- 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作;
缺点
- 需要为每一个类都配置一个 clone 方法;
- clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则;
- 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。
4、主要角色
- 抽象原型类:规定了具体原型对象必须实现的接口;
- 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象;
- 访问类:使用具体原型类中的 clone() 方法来复制新的对象;
5、深克隆与浅克隆
也就是深拷贝与浅拷贝
深克隆
创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址;
浅克隆
创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址;
6、通过Cloneable接口实现浅克隆
实体类
package com.zibo.design.one;
public class Dog implements Cloneable {
private final String name;
private final int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
System.out.println("原型创建成功!");
}
@Override
protected Object clone() throws CloneNotSupportedException {
System.out.println("圆形复制成功!");
return super.clone();
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
测试类
package com.zibo.design.one;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Dog dog = new Dog("小黑", 1);
Dog dog1 = (Dog)dog.clone();
Dog dog2 = (Dog)dog.clone();
Dog dog3 = (Dog)dog.clone();
System.out.println(dog);
System.out.println(dog1);
System.out.println(dog2);
System.out.println(dog3);
}
}
运行结果
原型创建成功!
圆形复制成功!
圆形复制成功!
圆形复制成功!
Dog{name='小黑', age=1}
Dog{name='小黑', age=1}
Dog{name='小黑', age=1}
Dog{name='小黑', age=1}
7、改良5
上面的例子是完全的克隆,一点属性都没有,实际生活中总要有所区分吧
实体类
package com.zibo.design.one;
public class Dog implements Cloneable {
private String name;
private final int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
System.out.println("原型创建成功!");
}
// 我们可以自定义克隆,传入名字,克隆之后改一个名字
protected Dog clone(String name) throws CloneNotSupportedException {
System.out.println("原型复制成功!");
Dog clone = (Dog)super.clone();
clone.name = name;
return clone;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
测试类
package com.zibo.design.one;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Dog dog = new Dog("大狗子", 1);
Dog dog1 = dog.clone("二狗子");
Dog dog2 = dog.clone("三狗子");
Dog dog3 = dog.clone("四狗子");
System.out.println(dog);
System.out.println(dog1);
System.out.println(dog2);
System.out.println(dog3);
}
}
运行结果
原型创建成功!
原型复制成功!
原型复制成功!
原型复制成功!
Dog{name='大狗子', age=1}
Dog{name='二狗子', age=1}
Dog{name='三狗子', age=1}
Dog{name='四狗子', age=1}
8、原型管理器
原型模式的扩展
概述
原型管理器(Prototype Manager)是将多个原型对象存储在一个集合中供客户端使用,它是一个专门负责克隆对象的工厂,其中定义了一个集合用于存储原型对象,如果需要某个原型对象的一个克隆,可以通过复制集合中对应的原型对象来获得。在原型管理器中针对抽象原型类进行编程,以便扩展;
功能类
package com.zibo.design.one;
import java.util.HashMap;
import java.util.Map;
public interface Dog extends Cloneable{
Dog clone() throws CloneNotSupportedException;
}
// 原型管理器
class PrototypeManager {
// 存放原型
private final Map map = new HashMap();
// 饿汉式实例化管理器
private static final PrototypeManager manager = new PrototypeManager();
// 装载所有原型
private PrototypeManager() {
map.put("bigDog",new BigDog("大狗子",10));
map.put("littleDog",new LittleDog("小狗子",1));
}
public static PrototypeManager getManager(){
return manager;
}
// 克隆原型
public Dog getDog(String key) throws CloneNotSupportedException {
return map.get(key).clone();
}
}
// 大狗原型
class BigDog implements Dog {
private final String name;
private final int age;
public BigDog(String name, int age) {
this.name = name;
this.age = age;
System.out.println("大狗原型创建成功!");
}
@Override
public Dog clone() throws CloneNotSupportedException {
System.out.println("大狗原型复制成功!");
return (Dog) super.clone();
}
@Override
public String toString() {
return "bigDog{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
// 小狗原型
class LittleDog implements Dog {
private final String name;
private final int age;
public LittleDog(String name, int age) {
this.name = name;
this.age = age;
System.out.println("小狗原型创建成功!");
}
@Override
public Dog clone() throws CloneNotSupportedException {
System.out.println("小狗原型复制成功!");
return (Dog) super.clone();
}
@Override
public String toString() {
return "littleDog{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
测试类
package com.zibo.design.one;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
PrototypeManager manager = PrototypeManager.getManager();
Dog bigDog = manager.getDog("bigDog");
System.out.println(bigDog);
Dog littleDog = manager.getDog("littleDog");
System.out.println(littleDog);
}
}
运行结果
大狗原型创建成功!
小狗原型创建成功!
大狗原型复制成功!
bigDog{name='大狗子', age=10}
小狗原型复制成功!
littleDog{name='小狗子', age=1}