原型模式
指定原型实例制定创建对象的类型,通过拷贝完成对象创建。
Java 的克隆机制
实现 Cloneable
标记接口
需要实现 clone
方法
package 设计模式.原型模式;
/**
* @author LiYang
* @Project Name: Java设计模式
* @Package Name: 设计模式.原型模式
* Created by MacBook Air on 2020/07/17.
* Copyright © 2020 LiYang. All rights reserved.
*/
public class Solution {
public static void main(String[] args) {
Product product = new Product();
Product clone = null;
try {
clone = ((Product) product.clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
clone.setId(1);
System.out.println(clone.toString());
}
}
class Product implements Cloneable{
int id = 2;
@Override
public String toString() {
return "Product{" +
"id=" + id +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
/**
* Creates and returns a copy of this object. The precise meaning
* of "copy" may depend on the class of the object. The general
* intent is that, for any object {@code x}, the expression:
* <blockquote>
* <pre>
* x.clone() != x</pre></blockquote>
* will be true, and that the expression:
* <blockquote>
* <pre>
* x.clone().getClass() == x.getClass()</pre></blockquote>
* will be {@code true}, but these are not absolute requirements.
* While it is typically the case that:
* <blockquote>
* <pre>
* x.clone().equals(x)</pre></blockquote>
* will be {@code true}, this is not an absolute requirement.
* <p>
* By convention, the returned object should be obtained by calling
* {@code super.clone}. If a class and all of its superclasses (except
* {@code Object}) obey this convention, it will be the case that
* {@code x.clone().getClass() == x.getClass()}.
* <p>
* By convention, the object returned by this method should be independent
* of this object (which is being cloned). To achieve this independence,
* it may be necessary to modify one or more fields of the object returned
* by {@code super.clone} before returning it. Typically, this means
* copying any mutable objects that comprise the internal "deep structure"
* of the object being cloned and replacing the references to these
* objects with references to the copies. If a class contains only
* primitive fields or references to immutable objects, then it is usually
* the case that no fields in the object returned by {@code super.clone}
* need to be modified.
* <p>
*
* 数组拷贝方式是浅拷贝
* The method {@code clone} for class {@code Object} performs a
* specific cloning operation. First, if the class of this object does
* not implement the interface {@code Cloneable}, then a
* {@code CloneNotSupportedException} is thrown. Note that all arrays
* are considered to implement the interface {@code Cloneable} and that
* the return type of the {@code clone} method of an array type {@code T[]}
* is {@code T[]} where T is any reference or primitive type.
* Otherwise, this method creates a new instance of the class of this
* object and initializes all its fields with exactly the contents of
* the corresponding fields of this object, as if by assignment; the
* contents of the fields are not themselves cloned. Thus, this method
* performs a "shallow copy" of this object, not a "deep copy" operation.
* <p>
* The class {@code Object} does not itself implement the interface
* {@code Cloneable}, so calling the {@code clone} method on an object
* whose class is {@code Object} will result in throwing an
* exception at run time.
*
* @return a clone of this instance.
* @throws CloneNotSupportedException if the object's class does not
* support the {@code Cloneable} interface. Subclasses
* that override the {@code clone} method can also
* throw this exception to indicate that an instance cannot
* be cloned.
* @see Cloneable
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
含有依赖注入的类的clone 方法
@Override
protected Object clone() throws CloneNotSupportedException {
// 修改clone 方法,实现深复制
// return super.clone();
Product clone = (Product) super.clone();
System.out.println(clone.toString());
Inner inner = ((Inner) clone.getInner().clone());
clone.setInner(inner);
return clone;
}
序列化实现拷贝
ArrayList .clone();
类及其子类实现 Serializable
接口
//序列化
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try(ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream)) {
outputStream.writeObject(this);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
try(ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream)){
Product product = ((Product) inputStream.readObject());
return product;
}catch (IOException e){
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
应用场景
代码不应该依赖于需要复制的对象的具体类事,使用Protoype模式
优点
1、可以不耦合具体类的情况下克隆对象
2、避免重的初始化代码
3、方便构建复杂对象
源码
org.springframwork.beans.factory.support.AvstrackBeanDefinition
java.util.Arrays
ArrayList