原型模式

示例

/**
 * TODO 序列化实现深拷贝
 * 
 * @author ZhangPeng
 * @date 2021年6月2日 下午4:11:29
 */
public class Person implements Cloneable,Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Integer id;
	private String name;
	private String email;
	private Date birthday;
	
	public Person(Integer id, String name, String email, Date birthday) {
		super();
		this.id = id;
		this.name = name;
		this.email = email;
		this.birthday = birthday;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		
		//把当前对象写入内存中
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(out);
			oos.writeObject(this);
			oos.close();
			
			//从内存中取出数据
			byte[] bytes = out.toByteArray();
			InputStream in = new ByteArrayInputStream(bytes);
			ObjectInputStream ois = new ObjectInputStream(in);
			Object clone = ois.readObject();
			ois.close();
			return clone;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", email=" + email
				+ ", birthday=" + birthday + "]";
	}
}
public class PrototypeTest {

	public static void main(String[] args) throws Exception {
		Person person = new Person(1,"卡卡罗特","xxx@163.com",Calendar.getInstance().getTime());
		Person person1 = (Person) person.clone();
		/**
		 * person1.getBirthday().setTime(0);
		 * person1.setBirthday(new Date(0));
		 * 
		 * 第一行的意思是:get到了共享对象date,然后设置time=0,所以person和person1的birthday都发生了改变;
		 * 第二行的意思是:set自身的属性,所以并不会对另一个对象产生影响
		 */
		person1.getBirthday().setTime(0);
		System.out.println(person);
		System.out.println(person1);
	}
}

克隆对单例的破坏

public class HungarySingleton implements Cloneable {
 
    private static final HungarySingleton hungarySingleton;
 
    static {
        hungarySingleton = new HungarySingleton();
    }
 
    private HungarySingleton() {
        if (hungarySingleton != null) {
            throw new RuntimeException("单例构造器防止反射调用");
        }
    }
 
    public static HungarySingleton getInstance() {
        return hungarySingleton;
    }
 
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        //return super.clone();//单例实现了克隆接口 可以利用反射破坏单例
        return hungarySingleton;//解决办法 即使通过反射调用clone方法 获取到的依然是原来的实例对象
    }
 }
public class TestSingle {
	public static void main(String[] args) throws Exception {
		HungarySingleton instance = HungarySingleton.getInstance();
		Method cloneMethod = HungarySingleton.class.getDeclaredMethod("clone");
		cloneMethod.setAccessible(true);
		HungarySingleton newInstance = (HungarySingleton) cloneMethod.invoke(instance);
		 
		System.out.println(instance);
		System.out.println(newInstance);
	}
}

结果:
com.demo.tcp.designpattern.HungarySingleton@6d06d69c
com.demo.tcp.designpattern.HungarySingleton@6d06d69c

上一篇:LeetCode题目1——单链表逆序


下一篇:带头结点的单链表的各种操作