1、原型模式
(1)概念
用原型实例指定创建对象的种类,并且通过拷贝这些模型创建新的对象。因为对于存在大量相同或相似对象,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源(原型模式基于内存二进制流的复制,要比new更快)
(2)好处
创建新的对象比较复杂的时候,可以利用原型模式简化对象的创建过程同时提高了效率
不用重新初始化对象,而是动态的获取对象运行时的状态
如果原始对象发生变化(增加或减少属性),其它的克隆的对象也会发生变化,不用修改代码
(3)缺点
需要为每一个类配备一个克隆方法,这对全新的类不是很难,但是对已有的类进行改造的时候需要修改源代码,违背了OCP原则
2、实现
(1)浅克隆
class Person implements Cloneable { int age = 8; int score = 100; Location loc = new Location("bj", 22); @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
Location类
class Location { String street; int roomNo; @Override public String toString() { return "Location{" + "street=‘" + street + ‘\‘‘ + ", roomNo=" + roomNo + ‘}‘; } public Location(String street, int roomNo) { this.street = street; this.roomNo = roomNo; } }
public static void main(String[] args) throws Exception { Person p1 = new Person(); Person p2 = (Person)p1.clone(); System.out.println(p2.age + " " + p2.score+" "+p2.loc); p1.loc.street = "sh"; System.out.println(p2.age + " " + p2.score+" "+p2.loc); }
8 100 Location{street=‘bj‘, roomNo=22} 8 100 Location{street=‘sh‘, roomNo=22}
创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。也就是说对于基本数据类型的成员变量进行的是值传递;
引用数据类型的数据,进行的是引用传递(将成员变量的内存地址复制一份给新的对象),原型中成员变量的值会影响到复制的成员变量的值。
依靠Object类,Object类中含有对象的克隆方法
(2)深克隆(重写clone方法)
class Person implements Cloneable { int age = 8; int score = 100; Location loc = new Location("bj", 22); @Override public Object clone() throws CloneNotSupportedException { Person p = (Person)super.clone();//基本数据类型的属性和String的克隆 p.loc = (Location)loc.clone();//引用数据类型的克隆 return p; } }
class Location implements Cloneable { String street; int roomNo; @Override public String toString() { return "Location{" + "street=‘" + street + ‘\‘‘ + ", roomNo=" + roomNo + ‘}‘; } public Location(String street, int roomNo) { this.street = street; this.roomNo = roomNo; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
public static void main(String[] args) throws Exception { Person p1 = new Person(); Person p2 = (Person)p1.clone(); System.out.println(p2.age + " " + p2.score+" "+p2.loc); p1.loc.street = "sh"; System.out.println(p2.age + " " + p2.score+" "+p2.loc); }
8 100 Location{street=‘bj‘, roomNo=22} 8 100 Location{street=‘bj‘, roomNo=22}
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。进本数据类型进行的是值传递,要为所有的引用数据类型的成员变量申请存储空间,并复制每一个引用数据类型成员变量所引用的对象(引用类型的成员变量还是引用数据类型)进行拷贝
(3)深度克隆(利用序列化和反序列化)
import java.io.Serializable; public class Person implements Serializable { private String name; public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name=‘" + name + ‘\‘‘ + ‘}‘; } }
要实现序列化或反序列化必须实现接口Serializable
import java.io.*; public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { Person person1 = new Person("Tom"); try {
//序列化 ByteArrayOutputStream bas =new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bas); oos.writeObject(person1);//以对象流的方式输出
//反序列化 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bas.toByteArray())); Person person2 =(Person) ois.readObject(); person2.setName("Jack"); bas.flush(); oos.flush(); bas.close(); oos.close(); ois.close(); System.out.println(person1); System.out.println(person2); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
Person{name=‘Tom‘}
Person{name=‘Jack‘}
3、在Spring中的运用
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> <bean name="student" class="pers.zhb.domain.Student" scope="singleton"></bean> </beans>
配置文件中的bean是以原型模式的方式进行创建的
获取对象
public void test1(){ ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");//创建容器对象 Student student1=(Student)applicationContext.getBean("student"); }
深度克(利用序列化和反序列化)
(1)创建Person类并实现序列化接口:
import java.io.Serializable; public class Person implements Serializable { private String name; public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name=‘" + name + ‘\‘‘ + ‘}‘; } }
要实现序列化或反序列化必须实现接口Serializable
(2)运用序列化与反序列化实现对象的克隆:
import java.io.*; public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { Person person1 = new Person("Tom"); try { ByteArrayOutputStream bas =new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bas); oos.writeObject(person1); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bas.toByteArray())); Person person2 =(Person) ois.readObject(); person2.setName("Jack"); bas.flush(); oos.flush(); bas.close(); oos.close(); ois.close(); System.out.println(person1); System.out.println(person2); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
Person{name=‘Tom‘}
Person{name=‘Jack‘}
原文:https://www.cnblogs.com/zhai1997/p/14423364.html