设计模式之原型模式
温馨提示:
本文最后更新于 2023年11月16日,已超过 433 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我。
原型模式
原型模式属于创建型设计模式。当直接创建对象的代价较大时,通过复制现有的实例来创建新的实例,不需要知道相应类的信息。例如:数据库查询、IO操作生成等等。
优缺点
优点
- 提高了对象的创建效率,节省时间和资源;
- 避免重复对象创建初始化的复杂性;
- 可以在运行时动态添加和删除对象;
- 可以保护原始对象,防止意外修改影响原对象;
缺点
- 不是所有对象一定都可以进行有效的复制;
- 必须实现Cloneable接口,并重写clone方法。
代码实现
浅拷贝
public class Car implements Cloneable{
private String brand;
private Tire tire;
private String color;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Tire getTire() {
return tire;
}
public void setTire(Tire tire) {
this.tire = tire;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", tire=" + tire +
", color='" + color + '\'' +
'}';
}
@Override
public Car clone() {
try {
return (Car) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
public class Tire implements Cloneable{
private String brand;
private String color;
@Override
public String toString() {
return "Tire{" +
"brand='" + brand + '\'' +
", color='" + color + '\'' +
'}';
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public Tire clone() {
try {
return (Tire) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
public static void main(String[] args) {
Tire tire = new Tire();
tire.setBrand("米其林");
tire.setColor("黑色");
Car bmw1 = new Car();
bmw1.setBrand("宝马");
bmw1.setColor("黑色");
bmw1.setTire(tire);
System.out.println(bmw1);
Car bmw2 = bmw1.clone();
tire.setBrand("马牌");
System.out.println(bmw1);
System.out.println(bmw2);
}
- 通过上面的图我们发现,当我们想给第一辆车换个轮胎的时候,第二辆车的轮胎同样被改变,这并不是我们想要的效果。而这里使用的是原型模式的浅拷贝模式。
- 那我们如何仅给第一辆车换新轮胎而不影响其他车辆呢?这时我们就可以使用深拷贝来实现。
深拷贝
方式一
public class Car implements Cloneable{
private String brand;
private Tire tire;
private String color;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Tire getTire() {
return tire;
}
public void setTire(Tire tire) {
this.tire = tire;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", tire=" + tire +
", color='" + color + '\'' +
'}';
}
@Override
public Car clone() {
try {
Car car = (Car) super.clone();
car.setTire(car.getTire().clone());
return car;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
方式二
通过序列化对象实现深拷贝。
public class Car implements Cloneable, Serializable {
private static final long serialVersionUID = -3682987459412388794L;
private String brand;
private Tire tire;
private String color;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Tire getTire() {
return tire;
}
public void setTire(Tire tire) {
this.tire = tire;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", tire=" + tire +
", color='" + color + '\'' +
'}';
}
@Override
public Car clone() {
try {
Car car = (Car) super.clone();
car.setTire(car.getTire().clone());
return car;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
public Car deepClone() {
ByteArrayOutputStream bas = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
bas = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bas);
oos.writeObject(this);
bis = new ByteArrayInputStream(bas.toByteArray());
ois = new ObjectInputStream(bis);
return (Car) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
try {
if (Objects.nonNull(bas)){
bas.close();
}
if (Objects.nonNull(oos)){
oos.close();
}
if (Objects.nonNull(bis)){
bis.close();
}
if (Objects.nonNull(ois)){
ois.close();
}
}catch (IOException e){
throw new RuntimeException(e);
}
}
}
}
深/浅拷贝
原型模式种拷贝对象可分为深拷贝和浅拷贝。
浅拷贝
- 当拷贝对象只包含基础数据类型时,直接将这些字段复制到新的对象中。
- 当拷贝对象包含引用数据类型时,克隆对象引用数据类型的地址。
深拷贝
- 不仅会复制基本数据类型的变量,还会给引用数据类型申请存储空间给对应变量赋值;
正文到此结束
- 本文标签: 设计模式
- 本文链接: https://www.58cto.cn/article/16
- 版权声明: 本文由程序言原创发布, 非商业性可自由转载、引用,但需署名作者且注明文章出处:程序言 》 设计模式之原型模式 - https://www.58cto.cn/article/16