烟台开发区建设局网站,第三方网站流量统计,如何确定网站建设空间,台州网站建设优化简介
原型模式#xff08;Prototype Pattern#xff09;是用于创建重复的对象#xff0c;同时又能保证性能。这种类型的设计模式属于创建型模式#xff0c;它提供了一种创建对象的最佳方式。
这种模式是实现了一个原型接口#xff0c;该接口用于创建当前对象的克隆。当直…简介
原型模式Prototype Pattern是用于创建重复的对象同时又能保证性能。这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式。
这种模式是实现了一个原型接口该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时则采用这种模式。
克隆
原型模式对某个对象进行克隆在最原始的古老方法就是通过new出实例使用与之相同的参数但是每次创建新的对象时候需要重新获取一下属性效率不佳。 例子如下
①、古老办法
本次使用lombok省的还需要写getsettoString坐标导入如下
dependencies!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.24/version/dependency
/dependencies
实体类使用lombok的Data注解
package com.lyd.demo.entity;
import lombok.Data;
/*** Author: lyd* Description:* Date: 2022-08-25*/
Data
public class Car {private String type;private String color;public Car(String type, String color) {this.type type;this.color color;}
}
使用古老办法使用new一个一个赋值很明显有些缺点每次都需要调用对象去获取属性
package com.lyd.demo.ancient;
import com.lyd.demo.entity.Car;
/*** Author: lyd* Description:* Date: 2022-08-25*/
public class Test {public static void main(String[] args) {Car car new Car(奔驰, black);// 复制更多对象Car c1 new Car(car.getType(), car.getColor());Car c2 new Car(car.getType(), car.getColor());Car c3 new Car(car.getType(), car.getColor());System.out.println(car: car hashcode: car.hashCode());System.out.println(c1: c1 hashcode: c1.hashCode());System.out.println(c2: c2 hashcode: c2.hashCode());System.out.println(c3: c3 hashcode: c3.hashCode());}
}
运行结果可见虽然是复制成功了但是效率明显很低。 ②、原型模式
用原型实例指定创建对象的种类通过拷贝实例创建新的对象。 例子如下代码 需要让car实现Cloneable并且实现clone方法。
package com.lyd.demo.entity;
import lombok.Data;
/*** Author: lyd* Description:* Date: 2022-08-25*/
Data
public class Car implements Cloneable {private String type;private String color;public Car(String type, String color) {this.type type;this.color color;}// 克隆实例Overrideprotected Object clone() throws CloneNotSupportedException {Car car null;car (Car) super.clone();return car;}
}
测试
package com.lyd.demo.entity;
/*** Author: lyd* Description:* Date: 2022-08-25*/
public class PrototypeTest {public static void main(String[] args) throws CloneNotSupportedException {Car car new Car(红旗, red);Car c1 (Car) car.clone();Car c2 (Car) car.clone();Car c3 (Car) car.clone();System.out.println(car: car hashcode: car.hashCode());System.out.println(c1: c1 hashcode: c1.hashCode());System.out.println(c2: c2 hashcode: c2.hashCode());System.out.println(c3: c3 hashcode: c3.hashCode());}
} 运行结果 定义一个原型类声明出克隆自己的接口。克隆的时候只要调用clone方法就可以实现对象克隆。 浅拷贝
对于数据类型是基本数据类型的成员变量浅拷贝会直接进行值传递也就是将该属性复制一份给新的对象。因为是两份不同的数据所以对其中一的对象的成员变量值进行修改不会影响另一个对象拷贝得到的数据。 对于数据类型是引用类型的成员变量比如说成员变量是某个数组某个类的对象等那么浅拷贝会进行引用传递也就是只是将该成员变量的引用指内存地址复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。 在Car类中加一个属性
public Car NewEnergy;
编写测试浅拷贝类
package com.lyd.demo.entity;
/*** Author: lyd* Description: 浅拷贝* Date: 2022-08-25*/
public class ShallowCopyTest {public static void main(String[] args) throws CloneNotSupportedException {Car car new Car(红旗, red);car.NewEnergy new Car(奔驰, blue);// 克隆Car c1 (Car) car.clone();Car c2 (Car) car.clone();Car c3 (Car) car.clone();System.out.println(car: car hashcode: car.hashCode() NewEnergy: car.NewEnergy hashcode: car.NewEnergy.hashCode());System.out.println(c1: c1 hashcode: c1.hashCode() NewEnergy: c1.NewEnergy hashcode: c1.NewEnergy.hashCode());System.out.println(c2: c2 hashcode: c2.hashCode() NewEnergy: c2.NewEnergy hashcode: c2.NewEnergy.hashCode());System.out.println(c3: c3 hashcode: c3.hashCode() NewEnergy: c3.NewEnergy hashcode: c3.NewEnergy.hashCode());}
} 测试结果 可见如果是基本数据类型那就会传递值将值赋给新的对象对于对象则只是进行引用传递。这种就是浅拷贝。这样会导致只要修改其中一个变量就会导致所有都修改例如 c2.NewEnergy.setColor(red); 之后在打印一次数据。 深拷贝
深拷贝复制变量值对于引用数据则递归至基本类型后再复制。深拷贝后的对象与原来的对象是完全隔离的互不影响对一个对象的修改并不会影响另一个对象。深拷贝相比于浅拷贝速度较慢并且花销较大。 重新定义两个实体类其中一个只有基本数据类型另一个包含引用数据类型
方式一通过重写clone()方法
Car: 在克隆的时候直接调用super.clone()来完成对基本数据类型的克隆通过引用数据类的clone方法在进行类型强制装换即可。
package com.lyd.demo.deep;
import lombok.Data;
import java.io.Serializable;
/*** Author: lyd* Description: 汽车类* Date: 2022-08-25*/
Data
public class Car implements Cloneable, Serializable {private String type;private String color;public NewEnergy newEnergy; // 引用数据类型public Car(String type, String color) {this.type type;this.color color;}// 克隆实例Overrideprotected Object clone() throws CloneNotSupportedException {Object object null;// 完成基本数据的装换object super.clone();// 对引用数据类型的属性单独处理Car car (Car) object;car.newEnergy (NewEnergy) newEnergy.clone();return car;}
}
NewEnergy
package com.lyd.demo.deep;
import lombok.Data;
import java.io.Serializable;
/*** Author: lyd* Description: 新能源类* Date: 2022-08-25*/
Data
public class NewEnergy implements Serializable, Cloneable {private String type;private String color;public NewEnergy(String type, String color) {this.type type;this.color color;}/*** 该类都是基本数据类型直接返回即可* return* throws CloneNotSupportedException*/Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
测试:
package com.lyd.demo.deep;
/*** Author: lyd* Description: 深拷贝* Date: 2022-08-25*/
public class DeepCopyTest {public static void main(String[] args) throws CloneNotSupportedException {Car car new Car(路虎, green);car.newEnergy new NewEnergy(路虎新能源, blue);Car c1 (Car) car.clone();Car c2 (Car) car.clone();System.out.println(car: car hashcode: car.hashCode() NewEnergy: car.newEnergy hashcode: car.newEnergy.hashCode());System.out.println(c1: c1 hashcode: c1.hashCode() NewEnergy: c1.newEnergy hashcode: c1.newEnergy.hashCode());System.out.println(c2: c2 hashcode: c2.hashCode() NewEnergy: c2.newEnergy hashcode: c2.newEnergy.hashCode());System.out.println();c1.newEnergy.setColor(red); // 修改System.out.println(car: car hashcode: car.hashCode() NewEnergy: car.newEnergy hashcode: car.newEnergy.hashCode());System.out.println(c1: c1 hashcode: c1.hashCode() NewEnergy: c1.newEnergy hashcode: c1.newEnergy.hashCode());System.out.println(c2: c2 hashcode: c2.hashCode() NewEnergy: c2.newEnergy hashcode: c2.newEnergy.hashCode());}
} 运行结果 可见不但完成了把引用对象进行拷贝修改c1的属性时不会影响其他的对象这就是深拷贝 方式二通过对象序列化
通过对象流的方式将对象进行序列化之后在进行反序列化完成深拷贝。这样的效果会更好。 只要在Car类中添加一个deepClone方法
// 方式二实现序列化
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);Car car (Car) ois.readObject();return car;} catch (Exception e) {e.printStackTrace();return null;} finally {// 关闭流try {ois.close();bis.close();oos.close();bos.close();} catch (IOException e) {e.printStackTrace();}}
}
测试只要调用deepClone方法就可以
Car c1 (Car) car.deepClone();
Car c2 (Car) car.deepClone(); 最后实验结果 小建议 理解设计模式不是一件简单的事情需要不断的学习和动手去练习才能理解。只有掌握好设计模式才能够真正的理解SpringAOP和Mybatis的底层原理。各位读者可以和我一样动手敲一敲代码甚至用不同的例子来做通过debug一步一步调试还有就是多看看别人的例子。能够有助于理解