创建型设计模式-原型模式
Posted vbirdbest
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了创建型设计模式-原型模式相关的知识,希望对你有一定的参考价值。
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。
-
抽象原型类:规定了具体原型对象必须实现的clone()方法。JDK已经提供了java.lang.Cloneable抽象原型类。
-
具体原型:实现抽象原型类的clone()方法,它是被复制的对象。
-
访问类:使用具体原型类的clone()方法来复制新的对象。
-
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,扔指向原有属性锁指向的对象的内存地址。如JDK中的Object提供的clone()方法。
-
深克隆:创建一个新对象,属性中应用的其他对象也会被克隆,不再指向原有对象的地址。
public class Object
protected native Object clone() throws CloneNotSupportedException;
public interface Cloneable
使用new关键字创建对象会调用构造方法,使用clone()方法克隆对象并不会调用构造方法。
什么场景使用原型模式
- 对象的创建非常复杂,可以使用原型模式快捷创建对象
- 对性能和安全要求比较高。可以按照我们自己的逻辑来创建对象。
浅克隆实现方式
方式一:java.lang.Cloneable接口
@Data
@RequiredArgsConstructor
@AllArgsConstructor
public class Attribute
private int age;
实现JDK自带的java.lang.Cloneable接口。
@Data
public class Sheep implements Cloneable
private String name;
private Attribute attribute;
public Sheep()
System.out.println("Sheep构造函数");
@Override
protected Sheep clone() throws CloneNotSupportedException
System.out.println("开始克隆羊");
return (Sheep)super.clone();
public class Client
public static void main(String[] args) throws Exception
Attribute attribute = new Attribute(2);
Sheep prototype = new Sheep();
prototype.setName("原型羊");
prototype.setAttribute(attribute);
Sheep copy = prototype.clone();
copy.setName("多莉(Dolly)");
attribute.setAge(3);
// 原型羊:3
System.out.println(prototype.getName() +":"+prototype.getAttribute().getAge());
// 多莉(Dolly):3
System.out.println(copy.getName()+ ":" + copy.getAttribute().getAge());
java.lang.Cloneable#clone()方法就是浅拷贝,所以当拷贝对象的时候只是拷贝对象的内存地址,所以一旦修改原型中的引用对象的属性,那么拷贝出来的对象也会跟着改变。
方式二:BeanUtils.copyProperties(Object source, Object target)
注意事项:
- BeanUtils.copyProperties() 属于浅拷贝,不同的是它也能拷贝两个不同类型的对象。浅拷贝注意事项
- 如果对象都是基本类型那么随便使用。
- 如果对象中的属性有引用类型,只要不去修改对象属性的字段也没什么问题。
- target 中的存在的属性,source中一定要有,但是source中可以有多余的属性。
- target、source中的属性要名字相同,才能被赋值,不然的话需要手动赋值。
- Spring的BeanUtils的copyProperties方法需要对应的属性有getter/setter和无参构造方法。
public class Main
public static void main(String[] args)
Sheep prototype = new Sheep();
prototype.setName("原型羊");
prototype.setAttribute(new Attribute(2));
Sheep target = new Sheep();
BeanUtils.copyProperties(prototype, target);
target.getAttribute().setAge(3);
System.out.println(prototype.getName() +":"+prototype.getAttribute().getAge());
System.out.println(target.getName()+ ":" + target.getAttribute().getAge());
深拷贝实现
方案一:通过对象序列化实现(每个对象都要实现序列化接口Serializable)。
@Data
@RequiredArgsConstructor
@AllArgsConstructor
public class Attribute implements Serializable
private int age;
@Data
public class Sheep implements Serializable
private String name;
private Attribute attribute;
public class Client
public static void main(String[] args) throws Exception
Attribute attribute = new Attribute(2);
Sheep prototype = new Sheep();
prototype.setName("原型羊");
prototype.setAttribute(attribute);
// 对象序列化到文件
String file = "/Users/mengday/Downloads/oos.txt";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(prototype);
oos.close();
// 序列化文件转对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Sheep copy = (Sheep)ois.readObject();
copy.getAttribute().setAge(3);
// 原型羊:2
System.out.println(prototype.getName() +":"+prototype.getAttribute().getAge());
// 多莉(Dolly):3
System.out.println(copy.getName()+ ":" + copy.getAttribute().getAge());
以上是关于创建型设计模式-原型模式的主要内容,如果未能解决你的问题,请参考以下文章