原型模式
定义:Prototype原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
原型模式的优点及适用场景
- 使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
- 使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
- 因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。
类图:
具体代码:
Cloneable接口相当于类图中的Prototype类,People是具体的实现了类
public class People implements Cloneable {
private String name;
private int age;
private ArrayList<Finger> list = new ArrayList<>();
public People clone() {
try {
People p = (People) super.clone();
ArrayList<Finger> list1 = new ArrayList<>();
for (Finger f : list) {
Finger f1 = f.clone();
list1.add(f1);
}
p.setList(list1);
return p;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public ArrayList<Finger> getList() {
return list;
}
public void setList(ArrayList<Finger> list) {
this.list = list;
}
}
为了实现浅拷贝和深拷贝的区别,所以特意加了一个Finger类,实现Cloneable接口
public class Finger implements Cloneable {
public Finger clone() {
try {
return (Finger) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
测试类
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
People people2 = new People();
people2.setName("张三");
people2.setAge(18);
ArrayList<Finger> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add(new Finger());
}
people2.setList(list);
Log.e("zhang", "people2:" + people2.toString() + " name:" + people2.getName() + "===age:" + people2.getAge());
for (Finger f2 : people2.getList()) {
Log.e("zhang", "people2: f:" + f2.toString());
}
People people3 = people2.clone();
Log.e("zhang", "people3:" + people3.toString() + " name:" + people3.getName() + "===age:" + people3.getAge());
for (Finger f3 : people3.getList()) {
Log.e("zhang", "people3: f:" + f3.toString());
}
}
}
打印的结果:
people2:www.weshared.yuanxingmode.People@1b198fdb name:张三===age:18
f:www.weshared.yuanxingmode.Finger@32192a78
f:www.weshared.yuanxingmode.Finger@1077d551
f:www.weshared.yuanxingmode.Finger@13aab1b6
people3:www.weshared.yuanxingmode.People@a974eb7 name:张三===age:18
f:www.weshared.yuanxingmode.Finger@34f27624
f:www.weshared.yuanxingmode.Finger@2f13758d
f:www.weshared.yuanxingmode.Finger@31283342
可以看出通过clone()方法拷贝出来的的是一个新的对象(内存地址值不同)
浅拷贝与深拷贝
浅拷贝实现方式:通过clone()方法克隆对象,但未对所持有的类的引用使用clone()方法,会导致类的引用有所持有的内存地址值是相同的。
public Finger clone() {
try {
return (Finger) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
深拷贝:clone出来的是一个独立的,完全拥有自己的内存地址值。
public People clone() {
try {
People p = (People) super.clone();
ArrayList<Finger> list1 = new ArrayList<>();
for (Finger f : list) {
Finger f1 = f.clone();
list1.add(f1);
}
p.setList(list1);
return p;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}