原型模式
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,无须知道对象创建的细节
适用于:
类初始化消耗较多资源;
循环体中生产大量对象的时候。
对象的创建过程比较麻烦,但复制比较简单的时候
优点:
原型模式性能比直接new一个对象性能好;
简化创建对象过程。
缺点:
对象必须重写Object克隆方法;
复杂对象的克隆方法写起来较麻烦(深克隆、浅克隆)
原型模式包含以下主要角色:
抽象原型类:规定了具体原型对象必须实现的接口。
具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
访问类:使用具体原型类中的 clone() 方法来复制新的对象。
1.创建一个水果类,实现cloneable克隆接口,因为属性都是简单的属性,没有包含引用类型,所以用浅克隆
public class Fruit implements Cloneable{
private String name;
private int count;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "Fruit{" +
"name='" + name + '\'' +
", count=" + count +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
2.测试输出
public class Test {
public static void main(String[]args) throws CloneNotSupportedException {
Fruit fruit=new Fruit();//创建一个初始的水果对象,设置一些属性
fruit.setName("水果");
fruit.setCount(5);
List list=new ArrayList();
for(int i=1;i<4;i++){
int count=fruit.getCount();
Fruit f=(Fruit)fruit.clone();//对初始的对象和属性进行克隆
//f.setName("水果"+i);
f.setCount(count+i);
list.add(f);
}
System.out.println(list);
}
}
//[Fruit{name='水果', count=6}, Fruit{name='水果', count=7}, Fruit{name='水果', count=8}]
上面这种这种方式会比直接在循环中创建Student性能好。
在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制,
当对象包含引用类型属性时,需要使用深克隆,比如Fruit包含Date属性时:
public class Fruit implements Cloneable{
private String name;
private int count;
private Date sale_time;//需要引用类型的属性
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Date getSale_time() {
return sale_time;
}
public void setSale_time(Date sale_time) {
this.sale_time = sale_time;
}
@Override
public String toString() {
return "Fruit{" +
"name='" + name + '\'' +
", count=" + count +
", sale_time=" + sale_time +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
//return super.clone();
Fruit fruit= (Fruit)super.clone();
//引用类型深克隆
Date date=(Date)fruit.getSale_time().clone();
fruit.setSale_time(date);
return fruit;
}
}
//测试输出
public class Test {
public static void main(String[]args) throws CloneNotSupportedException {
Fruit fruit=new Fruit();
fruit.setSale_time(new Date());//深克隆初始化对象里引用类型就需要先给值了,要不会报错
List list=new ArrayList();
for(int i=0;i<4;i++){
//int count=fruit.getCount();
Fruit f=(Fruit)fruit.clone();
f.setName("水果"+i);
f.setCount(i);
list.add(f);
}
System.out.println(list);
}
}
//[Fruit{name='水果0', count=0, sale_time=Fri Aug 28 15:03:57 CST 2020}, Fruit{name='水果1', count=1, sale_time=Fri Aug 28 15:03:57 CST 2020}, Fruit{name='水果2', count=2, sale_time=Fri Aug 28 15:03:57 CST 2020}, Fruit{name='水果3', count=3, sale_time=Fri Aug 28 15:03:57 CST 2020}]