原型模式精讲

原型模式是一种创建型模式,也是属于创建对象的一种方式,像西游记里面的孙悟空吹猴毛也属于原型模式,克隆出来了一群的猴子猴孙,还有细胞的分裂,spring中的Bean的生命周期好像有一个单例还有个原型,那个原型就是每次请求都复制一个对象出来,官方的定义是:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。在java里面有一个clone的方法是属于Object类的,java里的克隆有浅克隆和深克隆之分,下面通过代码来看看:

浅克隆

package pattern.prototype;
public class Person implements Cloneable {
    public String name;
    public String pass;
    public String[] arr;

    public Person(String name,String pass,String[] arr){
        this.name=name;
        this.pass=pass;
        this.arr=arr;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        Person person=(Person)super.clone();return person;
    }
}
package pattern.prototype;

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        String[] arr={"hello1","hello2"};
        Person person=new Person("zj","123",arr);
        Person p=(Person)person.clone();
        System.out.println(p.name);
        System.out.println(p.pass);
        p.name="jack";
        p.pass="666";
        p.arr[0]="wahaha";
        for (String favor : p.arr) {
            System.out.print(favor + " ");
        }
        System.out.println();
        for (String favor : person.arr) {
            System.out.print(favor + " ");
        }
        System.out.println();
    }
}

返回结果:

zj
123
wahaha hello2 
wahaha hello2 

通过上面可以看出来,p中的arr修改了值以后,person中的值也进行了修改,所以这是属于浅克隆,浅克隆,对于被克隆的类中成员变量都是基本数据类型,可以实现了两份数据;被克隆的类中成员变量是对象类型,那么这个成员变量还是原来的引用,修改为新对象的值,旧对象的该对象类型的成员变量还是会变化。

深克隆

package pattern.prototype;
public class Person implements Cloneable {
    public String name;
    public String pass;
    public String[] arr;

    public Person(String name,String pass,String[] arr){
        this.name=name;
        this.pass=pass;
        this.arr=arr;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        Person person=(Person)super.clone();
        person.arr=arr.clone();
        return person;
    }
}
package pattern.prototype;

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        String[] arr={"hello1","hello2"};
        Person person=new Person("zj","123",arr);
        Person p=(Person)person.clone();
        System.out.println(p.name);
        System.out.println(p.pass);
        p.name="jack";
        p.pass="666";
        p.arr[0]="wahaha";
        for (String favor : p.arr) {
            System.out.print(favor + " ");
        }
        System.out.println();
        for (String favor : person.arr) {
            System.out.print(favor + " ");
        }
        System.out.println();
    }
}

返回结果:

zj
123
wahaha hello2 
hello1 hello2 

数组中的两个值的修改是都不会影响的,因为他们属于两个对象,所以上面的是属于深克隆.从新生成了地址。但是重写clone方法实现深克隆比较麻烦,要对所有是对象类型的成员变量,进行重新创建实例,重新赋值; 集合类会更麻烦,比如说ArrayList虽然重写了clone(),但还是浅克隆,实现深克隆需要遍历所有的model,创建实例,重新赋值的。

序列化实现深克隆

package pattern.prototype;
import java.io.*;

public class Apple implements,Serializable {
    public String name;
    public int age;

    public Apple(String name,int age){
        this.name=name;
        this.age=age;
    }

    public Object deepClone(Object obj) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;
        try {
            oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
            return ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bos.close();
                oos.close();
                ois.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    
    public static void main(String[] args) {
        Apple apple=new Apple("aaa",18);
        Apple apple1 = (Apple) apple.deepClone(apple);
        System.out.println(apple1==apple);
    }
}

这种方式比较简单,不用写很多的冗余的代码,有利于代码的阅读。

 

posted @ 2018-10-03 12:24  ~无崖子~  阅读(250)  评论(0编辑  收藏  举报