原型模式
描述
原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制现有对象来创建新对象,而无需从头开始编写代码。
在原型模式中,一个原型对象作为模板,新的对象通过克隆这个原型对象而创建。这样可以避免使用相同的代码来创建相似的对象,同时也可以提高创建对象的效率。通常情况下,原型模式会使用一个原型管理器来存储和管理原型对象,以便在需要的时候进行复制。
原型模式适用于需要创建大量相似对象的场景,如图形编辑器中的图形对象、数据库中的数据对象、网络传输中的数据包等。通过使用原型模式,可以大大提高对象创建的效率和代码复用性。
实现
public class Client {
public static void main(String[] args) {
Car car = new Car("丰田", 140000);
Prototype prototype = new Prototype();
prototype.registerObj("丰田",car);
Car cloneCar = prototype.clone("丰田");
System.out.println(car == cloneCar);
System.out.println(cloneCar);
}
}
/**
* 原型对象
*/
class Prototype {
//存放实例的map
private Map<String, Object> prototypeMap;
public Prototype() {
this.prototypeMap = new HashMap<>();
}
//注册对象
public void registerObj(String name,Object o){
prototypeMap.put(name,o);
}
public void unRegisterObj(String name){
prototypeMap.remove(name);
}
public Car clone(String name){
return ((Car)(prototypeMap.get(name))).clone();
}
}
/**
* Car继承Cloneable
*/
class Car implements Cloneable{
private String carName;
private int price;
public Car(){
}
public Car(String carName, int price) {
this.carName = carName;
this.price = price;
}
public Car clone(){
try {
return (Car) super.clone();
} catch (CloneNotSupportedException e) {
return new Car(this.carName,this.price);
}
}
@Override
public String toString() {
return "Car{" +
"carName='" + carName + '\'' +
", price=" + price +
'}';
}
}
对于对象的拷贝是使用jdk自带的clone,那么就会有个问题,拷贝是属于深拷贝还是浅拷贝呢?
深拷贝:深拷贝(Deep Copy)是指在进行对象复制时,将被复制对象的所有成员变量都复制一份到新的对象中,而不是仅仅复制对象的引用。
浅拷贝:,浅拷贝(Shallow Copy)仅仅复制对象的引用,而不是对象本身的成员变量。因此,如果原对象发生变化,浅拷贝后的新对象也会受到影响。
我们来测试一下。我们把Car修改成以下代码
class Car implements Cloneable{
private String carName;
private int price;
private Object from;
public Car(){
}
public Car(String carName, int price,Object from) {
this.carName = carName;
this.price = price;
this.from = from;
}
public Car clone(){
try {
return (Car) super.clone();
} catch (CloneNotSupportedException e) {
return new Car(this.carName,this.price,this.from);
}
}
@Override
public String toString() {
return "Car{" +
"carName='" + carName + '\'' +
", price=" + price +
'}';
}
public String getCarName() {
return carName;
}
public int getPrice() {
return price;
}
public Object getFrom() {
return from;
}
}
当克隆后我们比对引用类型的属性
Car car = new Car("丰田", 140000,new Object());
Prototype prototype = new Prototype();
prototype.registerObj("丰田",car);
Car cloneCar = prototype.clone("丰田");
System.out.println(cloneCar.getFrom() == car.getFrom());
发现克隆的对象的引用属性和被克隆的对象引用属性的地址一致。
通过以上结论,我们可以知道,jdk的clone为浅拷贝。如果需要深拷贝,我们需要重新自己写一个克隆方法来进行深拷贝。
使用场景
-
当需要创建的对象具有相同的属性和方法时,但其状态不同,例如游戏中的敌人,它们具有相同的属性和方法,但具有不同的血量、攻击力等状态。
-
当创建对象的过程非常昂贵或复杂时,例如数据库连接对象、网络连接对象等。在这种情况下,通过复制现有对象,可以避免重复创建对象,从而提高性能。
-
当需要避免构造函数被反复调用时,例如在某些系统中,构造函数可能会执行一些昂贵的计算或操作,通过使用原型模式,可以避免这些计算或操作被反复执行