原型模式
简单理解就是,在拷贝对象的场景中,先指定一个对象为原型,然后拷贝这个原型创建更多的相同对象。
原型模式是一种创建型设计模式,允许一个对象再再创建另外一个可定制的对象。无需指定创建细节。
通过一个原型对象传给那个要发动创建的对象。对象.clone()
浅拷贝
对于数据类型是基础数据类型的成员变量,浅拷贝会直接进行值的传递,也就是会将该属性值复制一份给新的对象。如果成员变量是引用数据类型,比如数组,某个类等,那么浅拷贝就会进行引用传递。也就是只将该成员变量的引用值复制一份给新的对象,实际上复制后的对象所有指的对象是原型对象。属于同一个对象。以下就是浅拷贝的例子:
/**
* @description:
* @author:
* @create: 2022-04-07 16:21
*/
public class Sheep implements Cloneable {
private String name;
private String type;
private Integer age;
public Sheep(String name, String type, Integer age) {
this.name = name;
this.type = type;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", type='" + type + '\'' +
", age=" + age +
'}';
}
/**
* 重写克隆方法
* @return
*/
@Override
protected Object clone() {
Sheep sheep = null;
try {
sheep = (Sheep) super.clone();
} catch (Exception e) {
e.getMessage();
}
return sheep;
}
}
/**
* @description:
* @author:
* @create: 2022-04-07 16:36
*/
public class Clent {
public static void main(String[] args) {
Sheep sheep=new Sheep("小白","aa",12);
Sheep clone = (Sheep) sheep.clone();
Sheep clone1 = (Sheep) sheep.clone();
Sheep clone2 = (Sheep) sheep.clone();
System.out.println(sheep);
System.out.println(clone);
System.out.println(clone1);
System.out.println(clone2);
}
}
**深度拷贝**
复制对象的所有基本数据类型的成员值,为所有引用数据类型的成员申请存储空间,并复制每一个引用数据类型成员变量所引用的对象。也就是说对象进行深度拷贝要对整个对象进行拷贝
实现方式1: 重新clone 方法实现
实现方式2:通过对象序列化实现
举例:
```java
/**
* @description:
* @author:
* @create: 2022-04-07 17:18
*/
public class Milk implements Serializable, Cloneable{
private String name ;
private Integer price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public Milk(String name, Integer price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Milk{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
/**
* @description:
* @author:
* @create: 2022-04-07 16:21
*/
public class Sheep implements Serializable, Cloneable {
private String name;
private String type;
private Integer age;
private Milk milk;
public Sheep(String name, String type, Integer age) {
this.name = name;
this.type = type;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Milk getMilk() {
return milk;
}
public void setMilk(Milk milk) {
this.milk = milk;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", type='" + type + '\'' +
", age=" + age +
", milk=" + milk +
'}';
}
/**
* 重写克隆方法
* 深度克隆
*
* @return
*/
@Override
protected Object clone() {
Sheep sheep = null;
try {
sheep = (Sheep) super.clone();
sheep.milk = (Milk) sheep.milk.clone();
} catch (Exception e) {
e.getMessage();
}
return sheep;
}
/**
* 序列化方式拷贝
* @return
*/
public Object deepClone(){
ByteArrayOutputStream bos=null;
ObjectOutputStream oos=null;
ByteArrayInputStream bis=null;
ObjectInputStream ois=null;
try {
bos=new ByteArrayOutputStream();
oos=new ObjectOutputStream(bos);
oos.writeObject(this);
bis=new ByteArrayInputStream(bos.toByteArray());
ois=new ObjectInputStream(bis);
return ois.readObject();
}catch (Exception e){
return null;
}finally {
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
/**
* @description:
* @author:
* @create: 2022-04-07 16:36
*/
public class Clent {
public static void main(String[] args) {
/* Sheep sheep=new Sheep("小白","aa",12);
Sheep clone = (Sheep) sheep.clone();
Sheep clone1 = (Sheep) sheep.clone();
Sheep clone2 = (Sheep) sheep.clone();
System.out.println(sheep);
System.out.println(clone);
System.out.println(clone1);
System.out.println(clone2);*/
/*
克隆方式一
*/
Sheep sheep = new Sheep("小白", "aa", 12);
sheep.setMilk(new Milk("蒙古牛奶", 122));
Sheep clone01 = (Sheep) sheep.clone();
/* System.out.println(sheep.hashCode()+" "+sheep.getMilk().hashCode());
System.out.println(clone01.hashCode()+" "+clone01.getMilk().hashCode());*/
// 克隆方式二
Sheep sheep1 = (Sheep) sheep.deepClone();
System.out.println(sheep.hashCode() + " " + sheep.getMilk().hashCode() + " " + sheep.toString());
System.out.println(sheep1.hashCode() + " " + sheep1.getMilk().hashCode() + " " + sheep1);
}
}
小结
1,如果创建新的对象比较复杂的时候就可以使用原型模式简化对象的创建。也提供的效率。
2,在创建的过程是不用重新初始化对象而是动态的获取对象运行时的状态。也就是在创建之前如果对象的属性值变了,那么创建时是使用变化后的值来创建新的对象。原始对象的值发生改变时,克隆后的对象也会发生相应的改变。无需修改代码。
缺点:
需要为每一个类配置一个克隆的方法,对全新的类来说不是很难。如果要对已有的类进行改造就要违背了ocp 原则。