原型模式
介绍
原型模式:通过原型模式指定创建对象的种类,通过拷贝这些原型,创建新的对象。允许对象在创建另一个可定制的对象,无需知道细节。
原理:通过将原型对象传给要创建的对象,这个对象请求原型对象拷贝他们自己来实现(需要继承Cloneable) 对象.clone()
代码实现
原型类
/**
* @program: demo
* @description: 克隆羊
* @author: wfg
* @create: 2021-05-04 10:00
*/
@Data
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Sheep implements Cloneable {
/**
* @Description: 羊的属性
* @Author: wfg
*/
private String name;
private Integer age;
private String sex;
/**
* @Description: 必须要重写cloneable的clone方法
* @Author: wfg
*/
@Override
protected Object clone() {
Sheep sheep =null;
try{
//返回本类的克隆
sheep= (Sheep) super.clone();
}
catch ( CloneNotSupportedException e){
e.printStackTrace();
}
return sheep;
}
}
克隆类
/**
* @program: demo
* @description: 客户端,实现克隆
* @author: wfg
* @create: 2021-05-04 10:12
*/
public class TestPropoty {
public static void main(String[] args) {
Sheep sheep =new Sheep("duoli",10,"男");
//实现克隆
Sheep sheep1 =(Sheep)sheep.clone();
System.out.println(sheep);
System.out.println(sheep1);
}
}
浅拷贝
在克隆的时候,对于数据类型是基本类型或String时,浅拷贝会直接进行值传递,而对于引用类型时会将其引用值复制一份(不是再新建对象)因此两个变量都会指向同一个实例,其中一个修改里面的属性值时,另一个也会跟着修改。
实现
实现浅拷贝只需重写(如上文所示)默认的clone()方法。
深拷贝
会复制对象的所有基本数据类型和string的成员变量值,对于所有引用数据类型,会为其的成员变量申请存储空间,并复制每个引用数据类型的成员变量所引用的对象
实现1:通过重写clone方法(将被引用的对象进行拷贝)实现深拷贝
被引用的对象
/**
* @program: demo
* @description: 深拷贝-引用的对象
* @author: wfg
* @create: 2021-05-04 12:04
*/
@AllArgsConstructor
@ToString
public class DeepClone implements Serializable,Cloneable {
/**
* @Description: 属性
* @Author: wfg
*/
private String name;
private Integer age;
/**
* @Description: 由于此类属性都是string 因此深拷贝的此对象时只需重写默认clone方法
* @Author: wfg
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
进行拷贝的对象
/**
* @program: demo
* @description: 深拷贝 重写clone 方法实现
* @author: wfg
* @create: 2021-05-04 12:11
*/
@AllArgsConstructor
@ToString
public class DeepS implements Cloneable{
private String ss;
/**
* @Description: 深拷贝此对象
* @Author: wfg
*/
private DeepClone deep;
/**
* @Description: 在深拷贝时先拷贝基本类型,在单独拷贝引用类型
* @Author: wfg
*/
@Override
protected Object clone() {
DeepS ds=null;
try{
//基本数据类型和string先拷贝(此时deep指向的还是原来对象)
ds = (DeepS) super.clone();
//单独处理引用类型-通过引用类型里面的深拷贝进行创建一个新对象
ds.deep=(DeepClone) deep.clone();
}
catch ( CloneNotSupportedException e){
e.printStackTrace();
}
return ds;
}
}
实现方法2: 通过序列化实现,先将该对象序列化成流,再将其反序列化成对象(推荐)
/**
* @Description: 深拷贝 通过序列化将对象转成流,在通过返序列化将流转成对象,因此可完成
* @Author: wfg
*/
public Object xlClone(){
//创建流对象
//节点
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);
DeepS ds1= (DeepS) ois.readObject();
return ds1;
}
catch(Exception e){
e.printStackTrace();
return null;
}finally {
try{
//关闭流
bos.close();
oos.close();
bis.close();
bos.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
总结
1.创建对象比较复杂时,可以利用原型模式简化对象创建过程,同时提高效率
2.不需要重新初始化对象,动态获取对象运行状态
缺点:需要为每一个类配备一个克隆方法