原型模式也就是我们俗说的clone:
1.关于clone()方法
浅拷贝的例子:
class MyTest implements Cloneable {
String a;
ArrayList<String> list;
MyB b;
@Override
protected Object clone() {
try {
MyTest tmp=(MyTest) super.clone();
tmp.a=this.a;
tmp.list=this.list;
return tmp;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
private void test(){
MyTest t = new MyTest();
t.a = "aaa";
t.list = new ArrayList<String>();
t.list.add("0");
t.list.add("1");
t.b = new MyB("bbbbb");
MyTest clone = (MyTest) t.clone();
clone.a = "sss";
clone.list.add("2");
clone.b= new MyB("bbbbb2222222");
Log.i("info", "t.toString " + t.toString());
Log.i("info", "clone.toString " + clone.toString());
}
03-21 17:14:52.496 6534-6534/aidl.example.caiwei.aidlclient I/info: t.toString MyTest{a='aaa', b='bbbbb', list=[0, 1, 2]}
03-21 17:14:52.496 6534-6534/aidl.example.caiwei.aidlclient I/info: clone.toString MyTest{a='sss', b='bbbbb2222222', list=[0, 1, 2]}
可以看到输出的原始变量t,它的ArrayList类对象list长度发生了变化,但是它的MyB类对象b没有发生改变。
来看另一种写法:
private void test(){
MyTest t = new MyTest();
t.a = "aaa";
t.list = new ArrayList<String>();
t.list.add("0");
t.list.add("1");
t.b=new MyB("bbbbb");
MyTest clone = (MyTest) t.clone();
clone.a = "sss";
clone.list.add("2");
clone.b.b="bbbbb2222222";
Log.i("info", "t.toString " + t.toString());
Log.i("info", "clone.toString " + clone.toString());
}
03-21 17:12:42.483 6272-6272/aidl.example.caiwei.aidlclient I/info: t.toString MyTest{a='aaa', b='bbbbb2222222', list=[0, 1, 2]}
03-21 17:12:42.483 6272-6272/aidl.example.caiwei.aidlclient I/info: clone.toString MyTest{a='sss', b='bbbbb2222222', list=[0, 1, 2]}
可以看到输出的原始变量t,它的ArrayList类对象list长度发生了变化,它的MyB类对象b也发生了改变。
这是浅拷贝。
修改clone()方法为深拷贝(注意,需要修改MyB也为):
@Override
protected Object clone() {
try {
MyTest tmp = (MyTest) super.clone();
tmp.a=this.a;
tmp.list=(ArrayList<String>)this.list.clone();
tmp.b=(MyB)this.b.clone();
return tmp;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
03-21 17:27:59.620 7620-7620/aidl.example.caiwei.aidlclient I/info: t.toString MyTest{a='aaa', b='bbbbb', list=[0, 1]}
03-21 17:27:59.620 7620-7620/aidl.example.caiwei.aidlclient I/info: clone.toString MyTest{a='sss', b='bbbbb2222222', list=[0, 1, 2]}
可以看到打印结果,clone对象的修改不会影响到原始对象。
所以,Object类的clone方法执行的是浅拷贝,编写程序时要注意这个细节;如需要实现深拷贝,需要implements实现Cloneable接口,并重写clone方法。需要注意的另一个问题是,通过clone拷贝对象不会去执行构造函数。