作者:千珏
邮箱:wl625363199@gmail.com
公众号:千珏
标题:设计模式之原型模式(转载请标明出处)
Hello,各位观众老爷们大家好,千珏本珏又回来填坑了,按照我本来的想法设计模式应该写玩了,但是人算不如天算啊,最近几个月因为买房然后又买家具的事忙到了现在,还好,中间没有出什么太大的问题,事情已经忙的差不多了,不出意外的话,最近千珏要采取日更模式了,尽量把设计模式这个坑给填完吧,然后后面出一个新的系列的文章。
不说废话了,下面进入正文,原型模式大概可以说是最简单的一个设计模式了,因为java已经直接帮我们实现了,相信这里有小伙伴已经猜到是啥了,没错只要实现 了Cloneable接口,直接调用里面的clone这个方法,就可以直接克隆一个类了,但是他也是最难的设计模式,因为自己实现起来要考虑好多东西。
原型模式
定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
定义就是这么简单明了。
例子
上面提到过说java里面已经帮我们实现了原型模式,实现Cloneable接口就行了,下面我们来看一个demo.
public class Test implements Cloneable{
String age ;
String name;
public Test(String age, String name){
this.age = age;
this.name = name;
}
@Override
public Test clone(){
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
throw new RuntimeException(exception);
}
return (Test) object;
}
@Override
public String toString() {
return "Test{" +
"age='" + age + '\'' +
", name='" + name + '\'' +
'}';
}
public static void main(String[] args) throws IOException {
Test test = new Test("w","20");
Test test1 = test.clone();
System.out.println(test);
System.out.println(test1);
}
}
程序的输出是
Test{age=‘w’, name=‘20’}
Test{age=‘w’, name=‘20’}
可以看出test1
就是完全的复制了test
对象。
java里面的clone方法,是浅拷贝,浅拷贝的意思就是如果对象里面有引用对象,拷贝过来的时候不会在生成新的内存块,还是使用老的内存块,看个下面的例子就知道了。
class TestClone{
String age;
String name;
//省略getter,setter
}
public class Test implements Cloneable{
String age ;
String name;
TestClone testClone;
public Test(String age, String name){
this.age = age;
this.name = name;
testClone = new TestClone();
}
@Override
public Test clone(){
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
throw new RuntimeException(exception);
}
return (Test) object;
}
@Override
public String toString() {
return "Test{" +
"age='" + age + '\'' +
", name='" + name + '\'' +
", testClone=" + testClone +
'}';
}
public static void main(String[] args) throws IOException {
Test test = new Test("w","20");
Test test1 = test.clone();
System.out.println(test);
System.out.println(test1);
}
}
上面的输出结果是
Test{age=‘w’, name=‘20’, testClone=com.wl.common.string.TestClone@1540e19d}
Test{age=‘w’, name=‘20’, testClone=com.wl.common.string.TestClone@1540e19d}
可以看到testclone
这个对象的内存块克隆过后输出是一样的,这个不是我们想要的结果,如果我们想在test1
中修改TestClone
这个对象,那么test
这个对象也就会跟着修改这个当然不是我们想要的值。
那么如何使用深拷贝呢,其实很简单就是把上面的TestClone类也实现Cloneable接口就好了。
class TestClone implements Cloneable{
String age;
String name;
//省略getter,setter
@Override
public TestClone clone(){
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
throw new RuntimeException(exception);
}
return (TestClone) object;
}
}
public class Test implements Cloneable{
String age ;
String name;
TestClone testClone;
public Test(String age, String name){
this.age = age;
this.name = name;
testClone = new TestClone();
}
@Override
public Test clone(){
Object object = null;
try {
object = super.clone();
((Test)object).testClone = this.testClone.clone();
} catch (CloneNotSupportedException exception) {
throw new RuntimeException(exception);
}
return (Test) object;
}
@Override
public String toString() {
return "Test{" +
"age='" + age + '\'' +
", name='" + name + '\'' +
", testClone=" + testClone +
'}';
}
public static void main(String[] args) throws IOException {
Test test = new Test("w","20");
Test test1 = test.clone();
System.out.println(test);
System.out.println(test1);
}
}
改造TestClone过后,再对程序进行输出
Test{age=‘w’, name=‘20’, testClone=com.wl.common.string.TestClone@1540e19d}
Test{age=‘w’, name=‘20’, testClone=com.wl.common.string.TestClone@677327b6}
这个时候我们就完成深克隆了,这个时候就算改变test1
对象里面的子对象时,test
对象里面的子对象也不会受到干扰,这个才是我们想要的结果。
但是如果有n个子对象的话,实现深拷贝的话就比较困难了,这也是java里面原型对象不可避免的缺点,所以还是要看业务需求呀。
总结
这篇最主要就是讲了java里面如何实现原型模式,java对原型模式实现了语言级的支持,所以实现起来还是挺简单的。相信看完了这一篇文章的看官老爷们应该对原型模式都不陌生了吧。
下一篇预告 策略模式,我们明天见。