设计模式:原型模式

一、引

我们在日常的开发中,可能会遇到需要重复创建相同或者类似的对象,这个时候如果使用实例化(new),那么我们需要多少个对象,就需要实例化多少次,这不仅会导致代码重复的灾难,还难以对已实例化的对象进行修改,那么这个时候就需要一种设计思想,在需要对象的时候,尽量避免实例化,优化程序结构,且方便我们进行修改,这种模式就是原型模式,可以理解为利用原型进行复制。

二、问题

有一个简历的类(Resume),现在需要多份简历,如果通过一份简历复制多份?

三、理解及实现

这个时候有人会说,这还不简单new一个类,然后不断的赋值就好了,像下列这样:

Resume a = new Resume();
Resume b = a;
Resume c = b;

会这样写的,说明基础还不够扎实,因为,java中对象的单纯赋值,并不是复制一个新的对象,而是引用,所以要注意了,不能这么写,那么要怎么写呢?思路很简单,我们需要先实例化一个对象,然后通过这个对象复制(结构+数据)出无数的新对象,这样每个对象都是独立的,而且还能在原对象数据的基础上进行更改,方便很多,说起来容易,我们要怎么做呢?我们先来看看原型模式的结构图:

从图中我们可以理解到,需要定义一个原型抽象类,这个类有一个克隆的接口,一般在实体类的这个接口中,使用克隆方法进行克隆,但是由于克隆实在是太常用了,所以java早就给我们定义好了这个抽象类(Cloneable),所以我们的实体类直接实现这个接口就行了。具体代码如下:

public class Resume implements Cloneable {
	private String name;
	private String sex;
	private int age;
	private WorkExperience workExperience;
	
	public Resume(String name) {
        this.name = name;
        workExperience = new WorkExperience();
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void setPersonal(String sex, int age) {
        this.age = age;
        this.sex = sex;
    }
 
    public void setWork(String timeArea, String company) {
    	workExperience.timeArea = timeArea;
    	workExperience.company = company;
    }
    
    @Override
    public Resume clone() throws CloneNotSupportedException {
        return (Resume)super.clone(); 
    }
    
    public void display() {
        System.out.println(this.name + " " + this.sex + " " + this.age + " " + this.sex);
        System.out.print("Work experience: " + this.workExperience.timeArea);
        System.out.println(" " + this.workExperience.company);
    }
}
public class WorkExperience {
	public String timeArea = null;
    public String company = null;
}
public class Main {

	public static void main(String[] args) throws CloneNotSupportedException {
		Resume resume1 = new Resume("Jobs");
        resume1.setPersonal("Male", 26);
        resume1.setWork("2016年8月1日 - 2018年6月30日", "Huawei");
        
        Resume resume2 = resume1.clone();
        resume2.setName("Tom");
        resume2.setWork("2018年7月1日 - 2019年1月10日", "Baidu");
        
        resume1.display();
        resume2.display();
	}

}

运行之后,你会发现一件很奇怪的事情,就是名字正常的更改了,但两个对象的工作经历都变成了最后一次更改时的值,这是怎么回事呢?这就涉及到了浅复制和深复制的概念。因为clone这个方法,对于值类型的属性进行逐位复制,但对于引用的对象,只复制引用而不复制引用的对象,所以,在例子中WorkExperience是被引用的对象,所以例子中的两个对象都在对一个WorkExperience实例进行修改,才会导致以上的问题,这就是浅复制,那么我们如何进行深复制呢?我们在clone进行操作就行,代码如下:

@Override
    public Resume clone() throws CloneNotSupportedException {
        int age = this.age;
        String sex = this.sex;
        String name = new String(this.name);
        
        Resume copy = new Resume(name, famMem); 
        copy.setPersonal(sex, age);
        copy.setWork(this.work.timeArea, this.work.company);
        return copy;
    }

 

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