GoF设计模式-原型模式

    原型模式(重要):    
        当需要多次创建相同或相似对象时,可以复制这个对象。
    
    浅克隆:复制对象本身和基本类型的成员变量(String当做引用类型看待),对于引用类型的成员变量仅复制其引用地址,而引用对象不复制。通过覆盖Java中的clone()方法来实现浅克隆,浅克隆的对象须实现Cloneable接口。
    深克隆:复制对象全部的内容,对于引用类型的成员变量,由于在堆中复制了其引用对象,所以引用地址肯定发生了变化。在Java中,通过序列化的方式实现深克隆。将原有对象写入流中,写到流中的对象是原有对象的一个拷贝,然后从流中读出来实现深克隆,深克隆的对象须实现Serializable接口。
    浅克隆与深克隆的区别是引用类型的成员对象是否复制。

    原型模式的适用场景:
        1.创建新对象的成本过大,需要多次创建相同或相似对象时
        2.系统要保存对象的状态,而对象的状态变化很小,对象占用的内存很小,可以使用原型模式配合备忘录模式来应用。如果对象的状态变化或占用的内存很大,可以采用状态模式。
    
    原型模式的应用:
        1.在Struts2中为了保证线程的安全性,Action对象的创建使用了原型模式,当访问一个已经存在Action对象时,通过克隆的方式创建一个新对象,从而保证对象中定义的变量无须进行加锁而实现同步。
    
    原型模式的优点:
        1.简化对象的创建过程,提高对象的创建效率
        2.由于克隆方法在原型类的内部,因此增加新的原型类不需要修改原有代码
        3.可以使用深克隆保存对象的状态
    
    原型模式的缺点:
        1.当要克隆已有的类时,需要修改原有代码,违背了开闭原则
        2.实现深克隆需要编写较为复杂的代码
            
        原型模式的例子:

要克隆的对象

public class Student implements Cloneable,Serializable{
	
	private String stuName;
	private int stuAge;
	private School school;
	
	/**
	 * 
	 * @Description: 浅克隆,需要实现Cloneable接口
	 * @author doudou
	 * @date 2019年10月8日
	 * @return
	 * @throws
	 * @return
	 * @see java.lang.Object#clone()
	 */
	public Object clone() {
		Student student = null;
		try {
			student = (Student) super.clone();
		} catch (Exception e) {
			System.out.println("Clone failure");
		}
		return student;
	}
	
	/**
	 * 
	 * @Description: 深克隆
	 * @author doudou
	 * @date 2019年10月8日
	 * @return
	 * @throws IOException
	 * @throws ClassNotFoundException
	 * @throws
	 * @return
	 */
	public Object deepClone() throws IOException, ClassNotFoundException {
		//将对象写入流中
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
		objectOutputStream.writeObject(this);
		
		//将对象从流中取出
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
		ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
		return objectInputStream.readObject();
	}

	public String getStuName() {
		return stuName;
	}

	public void setStuName(String stuName) {
		this.stuName = stuName;
	}

	public int getStuAge() {
		return stuAge;
	}

	public void setStuAge(int stuAge) {
		this.stuAge = stuAge;
	}

	public School getSchool() {
		return school;
	}

	public void setSchool(School school) {
		this.school = school;
	}
	
}
public class School implements Serializable{
	
}

测试类:

public class Main {
	public static void main(String[] args) throws ClassNotFoundException, IOException {
		Student student = new Student();
		School school = new School();
		student.setSchool(school);
		student.setStuAge(10);
		student.setStuName("doudou");
		
		Student shallowClone = (Student) student.clone();
		Student deepClone = (Student) student.deepClone();
		
		System.out.println("student:"+student.toString());
		
		System.out.println("shallowClone:"+(shallowClone.toString()));
		System.out.println("shallowClone==student?"+(shallowClone==student));
		System.out.println("shallowClone.equals(student)?"+(shallowClone.equals(student)));
		System.out.println("shallowClone.getStuName()==student.getStuName()?"+(shallowClone.getStuName()==student.getStuName()));
		
		System.out.println("deepClone:"+(deepClone.toString()));
		System.out.println("deepClone==student?"+(deepClone==student));
		System.out.println("deepClone.equals(student)?"+(deepClone.equals(student)));
		System.out.println("deepClone.getStuName()==student.getStuName()?"+(deepClone.getStuName()==student.getStuName()));
	
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章