在开发一个界面的时候,里面有多个Button,这些对象的属性内容相似。如果一个个实例化Button对象,并设置其属性,那么代码量将会增多。
通过一个原型对象克隆出多个一模一样的对象,该模式被称为原型模式。
图 原型模式
Prototype: 抽象原型类,是声名克隆方法的接口,也可以是具体原型类的公共父类。
ConcretePrototype:具体原型类,实现了克隆方法,在克隆方法中返回自己的一个克隆对象。
Client:客户类,让一个原型对象克隆自身从而创建一个新的对象。
public interface ButtonClone {
ButtonClone cloneBtn();
}
public class Button implements ButtonClone{
private Double width;
private Double height;
public Double getWidth() {
return width;
}
public void setWidth(Double width) {
this.width = width;
}
public Double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
@Override
public ButtonClone cloneBtn() {
Button newBtn = new Button();
newBtn.setHeight(this.height);
newBtn.setWidth(this.width);
return newBtn;
}
}
1 浅克隆与深克隆
浅克隆,如果源对象的成员变量是值类型,将复制一份给克隆对象,如果源对象的成员变量是引用类型,则将引用对象的地址复制一份给对象。
深克隆,无论源对象的成员变量是值类型还是引用类型,都将复制一份给目标对象。
1.1 浅克隆
Java的Object类提供了一个clone()方法,可以将一个Java对象浅克隆。能实现克隆Java类必须实现一个标识接口Cloneable,表示这个类支持被复制。
public class ConcretePrototype implements Cloneable{
private String name;
private String type;
private List<String> list = new ArrayList<>();
public ConcretePrototype(String name, String type) {
this.name = name;
this.type = type;
}
@Override
public String toString() {
return "ConcretePrototype{" +
"name='" + name + '\'' +
", type='" + type + '\'' +
", list=" + list +
'}';
}
public static void main(String[] args) throws CloneNotSupportedException {
ConcretePrototype prototype = new ConcretePrototype("实际类型", "浅克隆");
System.out.println("prototype:" + prototype);
Object clone = prototype.clone();
System.out.println("clone:" + clone);
prototype.list.add("hello");
System.out.println("clone:" + clone);
}
}
1.2 深克隆
深克隆,除了对象本身被复制外,对象所包含的所有成员变量也将被复制。在Java中,如果需要实现深克隆,可以通过序列化等方式来实现。需要实例化的对象其类必须实现Serializable接口,否则无法实现序列化操作。
public class CusForm implements Serializable , Cloneable{
private String name;
private CusFile cusFile;
public CusForm(String name, CusFile cusFile) {
this.name = name;
this.cusFile = cusFile;
}
public static void main(String[] args) throws IOException, ClassNotFoundException, CloneNotSupportedException {
CusForm cusForm = new CusForm("表单", new CusFile());
System.out.println(cusForm);
System.out.println(cusForm.clone()); //java浅克隆,对象成员变量直接复制地址
CusForm deepCloneObj = cusForm.deepClone();
System.out.println(deepCloneObj);
// 运行结果
// CusForm{name='表单', cusFile=com.huangmingfu.prototype.deep.CusForm$CusFile@1b6d3586}
// CusForm{name='表单', cusFile=com.huangmingfu.prototype.deep.CusForm$CusFile@1ddc4ec2}
// CusForm{name='表单', cusFile=com.huangmingfu.prototype.deep.CusForm$CusFile@1b6d3586}
}
public CusForm deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(this);
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
return (CusForm) objectInputStream.readObject();
}
@Override
public String toString() {
return "CusForm{" +
"name='" + name + '\'' +
", cusFile=" + cusFile +
'}';
}
private static class CusFile implements Serializable{}
}
2 原型管理器
将多个原型对象存储在一个集合中供客户端使用,它是一个专门复制克隆对象的工厂。其中定义了一个集合用于存储原型对象。
图 原型管理器文章来源:https://www.toymoban.com/news/detail-588358.html
public class DeepClone implements Serializable {
public DeepClone deepClone() {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(this);
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
return (DeepClone)objectInputStream.readObject();
} catch (Exception e) {
System.out.println(e.getMessage());
}
return null;
}
}
public class ConcreteA extends DeepClone{
private final String name = "concreteA";
@Override
public String toString() {
return "ConcreteA{" +
"name='" + name + '\'' +
'}' + super.toString();
}
}
public class ConcreteB extends DeepClone{
private final String name = "ConcreteB";
@Override
public String toString() {
return "ConcreteB{" +
"name='" + name + '\'' +
'}' + super.toString();
}
}
public class PrototypeManager {
private final Map<Class<? extends DeepClone>,DeepClone> prototypeMap = new HashMap<>();
private final Set<Class<? extends DeepClone>> classes = new HashSet<>();
private PrototypeManager() {}
private static class HolderClass {
private final static PrototypeManager instance = new PrototypeManager();
}
public static PrototypeManager getInstance() {
return HolderClass.instance;
}
public void addPrototype(DeepClone deepClone) {
if (classes.add(deepClone.getClass())) {
prototypeMap.put(deepClone.getClass(),deepClone);
}
}
public DeepClone getClone(Class<? extends DeepClone> cls) {
DeepClone deepClone = prototypeMap.get(cls);
if (deepClone == null) {
throw new RuntimeException("克隆体不存在");
}
return deepClone.deepClone();
}
}
public class Client {
public static void main(String[] args) {
ConcreteA concreteA = new ConcreteA();
ConcreteB concreteB = new ConcreteB();
PrototypeManager prototypeManager = PrototypeManager.getInstance();
System.out.println(concreteA);
System.out.println(concreteB);
prototypeManager.addPrototype(concreteA);
prototypeManager.addPrototype(concreteB);
System.out.println("克隆分割线---------------");
DeepClone deepCloneA = prototypeManager.getClone(ConcreteA.class);
DeepClone deepCloneB = prototypeManager.getClone(ConcreteB.class);
System.out.println(deepCloneA);
System.out.println(deepCloneB);
// 运行结果
// ConcreteA{name='concreteA'}com.huangmingfu.prototype.manager.ConcreteA@1b6d3586
// ConcreteB{name='ConcreteB'}com.huangmingfu.prototype.manager.ConcreteB@4554617c
// 克隆分割线---------------
// ConcreteA{name='concreteA'}com.huangmingfu.prototype.manager.ConcreteA@30dae81
// ConcreteB{name='ConcreteB'}com.huangmingfu.prototype.manager.ConcreteB@1b2c6ec2
}
}
3 适用场景
当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建工厂,通过复制一个已有实例可以提高新实例的创建效率。文章来源地址https://www.toymoban.com/news/detail-588358.html
- 创建新对象成本较大。
- 对象的状态变化很小,且系统需要保存对象的状态时。
- 需要创建许多相似对象。
到了这里,关于原型模式-克隆一个对象的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!