一、介绍
原型模式适用于创建重复对象,同时也能保证性能。该模式是创建对象的最佳方式。
二、实现
需要创建的对象要实现Cloneable接口,并且重写clone方法。
三、实例
public class Student implements Cloneable{
private String name;
private Integer age;
private Integer height;
private Integer weight;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) &&
Objects.equals(age, student.age) &&
Objects.equals(height, student.height) &&
Objects.equals(weight, student.weight);
}
@Override
public int hashCode() {
return Objects.hash(name, age, height, weight);
}
}
public static void main(String[] args){
try {
Student student = new Student();
student.setName("张三");
student.setAge(20);
student.setHeight(180);
student.setWeight(65);
Student student1 = (Student) student.clone();
System.out.println(student.equals(student1));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
测试输出结果为:true
可以看到克隆之后的两个对象是完全相等的。
如果在属性中加一个引用类型,当克隆之后修改其中一个对象的引用类型的值,其余的都会改变,这是应为在克隆时引用不会创建新的对象,而是指向存在的对象的地址,所以才会有更改一个之后其余的对象的引用值也会改变,这也是浅克隆,如果不希望改变就要用深克隆,引用对象也创建一个新的对象。
以同样上面的例子为例,在属性中添加一个List,我们进行深克隆,深克隆的方法有很多,这里我们就用序列化的方式进行深克隆。
public class Student implements Cloneable, Serializable {
private String name;
private Integer age;
private Integer height;
private Integer weight;
private List<String> list;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
protected Object clone() throws CloneNotSupportedException {
super.clone();
Student student = null;
try{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(baos);
os.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream is = new ObjectInputStream(bais);
student = (Student) is.readObject();
}catch (Exception e){
e.printStackTrace();
}finally {
}
return student;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) &&
Objects.equals(age, student.age) &&
Objects.equals(height, student.height) &&
Objects.equals(weight, student.weight) &&
Objects.equals(list, student.list);
}
@Override
public int hashCode() {
return Objects.hash(name, age, height, weight, list);
}
}
public static void main(String[] args){
try {
Student student = new Student();
student.setName("张三");
student.setAge(20);
student.setHeight(180);
student.setWeight(65);
List<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
student.setList(list);
Student student1 = (Student) student.clone();
System.out.println(student.equals(student1));
student1.getList().remove(1);
System.out.println(student.getList());
System.out.println(student1.getList());
} catch (Exception e) {
e.printStackTrace();
}
}
试输出结果为:true
两个list也不一样,并没有因为改变了其中一个而影响另一个。
四、优点
1、比new一个对象效率更高,因为它是直接操作的内存中的二进制流。
五、缺点
1、无法于单例模式结合使用。
2、深克隆时需要自己实现。